diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfa1a4ac96cc2e4708a0bf268955f9070bb52f08..b24b1360750f2b7b17ec6c79edeacabec1eec336 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,30 @@
+0.42.0-beta2
+=============
+* Framework improvements:
+    * Added composer.lock to the repository
+* Various improvements:
+    * Magento PSR-3 compliance
+    * Updated file iterators to work with symlinks
+    * Replaced end-to-end test for advanced search with injectable test
+    * Replaced end-to-end test for quick search with injectable test
+* Fixed bugs:
+    * Fixed an issue where an exception occurred when adding configurable products to cart from the wishlist
+    * Modify .gitignore CE according to new repos structure (MAGETWO-32095)
+    * Fixed an issue where the 'Not %Username%?' link was displayed for a logged in user while pages were loaded
+    * Fixed an issue where Shopping Cart Price Rules based on product attributes were not applied to configurable products
+    * Fixed an issue where the Tax Class drop-down field on New Customer Group page contained the 'none' value when a tax class already existed
+    * Fixed an issue where the 'Credit Memo' button was absent on the Invoice page for payments
+    * Fixed an issue where incorrect totals were shown in the Coupon Usage report
+    * Fixed an issue where an error occurred and the "Append Comments" checkbox was cleared when submitting an order in the backend
+    * Fixed an issue where the Transactions tab appeared in the backend for orders where offline payment methods were used
+    * Fixed an issue with the extra empty line appearing in the Customer Address template
+* Github requests:
+    * [#853](https://github.com/magento/magento2/pull/853) -- Fix spelling error in Customer module xml
+    * [#858](https://github.com/magento/magento2/pull/858) -- Clicking CMS page in backend takes you to the dashboard
+    * [#858](https://github.com/magento/magento2/issues/816) -- Clicking CMS page takes you to the dashboard
+    * [#859](https://github.com/magento/magento2/pull/859) -- Fix email template creation date not being persisted
+    * [#860](https://github.com/magento/magento2/pull/860) -- Fix currency and price renderer
+
 0.42.0-beta1
 =============
 * Fixed bugs:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f3e88912e5bc9d9b0171783fcfaa246d87a8dbec..673dcfb25a05d495d2e859db42c041e39634791c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,28 +1,31 @@
-# Contribution Guide
+# Contributing to Magento 2 code
 
-The Magento 2 development team will review all issues and contributions submitted by the community of developers. Contributions can take the form of new components/features, changes to existing features, tests, documentation (such as developer guides, user guides, examples, or specifications), bug fixes, optimizations or just good suggestions. To assist in the expediency of the review process, we strongly encourage you to follow all the proper requirements stated below in Definition of Done, before submitting any code for consideration.
+Contributions to the Magento 2 codebase are done using the fork & pull model.
+This contribution model has contributors maintaining their own copy of the forked codebase (which can easily be synced with the main copy). The forked repository is then used to submit a request to the base repository to “pull” a set of changes (hence the phrase “pull request”).
 
-## Contribution Process
+Contributions can take the form of new components/features, changes to existing features, tests, documentation (such as developer guides, user guides, examples, or specifications), bug fixes, optimizations or just good suggestions.
 
-If you are a new GitHub user, we recommend that you create your own [free github account](https://github.com/signup/free). By doing that, you will be able to collaborate with the Magento 2 development team, “fork” the Magento 2 project and be able to easily send “pull requests”.
-
-1. Search current [listed issues](https://github.com/magento/magento2/issues) (open or closed) for similar proposals of intended contribution before starting work on a new contribution.
-2. Review the [Contributor License Agreement](https://github.com/magento/magento2/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.html) if this is your first time contributing.
-3. Create and test your work.
-4. Fork the Magento 2 repository according to [github's Fork A Repo instructions](https://help.github.com/articles/fork-a-repo) and when you are ready to send us a Pull Request – follow [github's Using Pull Requests instructions](https://help.github.com/articles/using-pull-requests).
-5. Once your contribution is received, Magento 2 development team will review the contribution and collaborate with you as needed to improve the quality of the contribution.
+The Magento 2 development team will review all issues and contributions submitted by the community of developers in the first in, first out order. During the review we might require clarifications from the contributor. If there is no response from the contributor for two weeks, the issue is closed.
 
-### Contribution Acceptance Criteria
 
-1. Code changes must be covered with automated tests and supplied along with the patch (or fork). Author chooses the best approach for testing as deemed necessary. See [Magento Automated Testing Standard](https://github.com/magento/magento2/wiki/Magento-Automated-Testing-Standard) for additional guidance.
-2. New features or proposals must be supplied with documentation -- functional (how a feature works) or technical (how it is implemented/designed), or both.
+## Contribution requirements
 
-## Frequently Asked Questions
+1. Contributions must adhere to [Magento coding standards](http://devdocs.magento.com/guides/v1.0/coding-standards/bk-coding-standards.html).
+2. Pull requests (PRs) must be accompanied by a meaningful description of their purpose. Comprehensive descriptions increase the chances of a pull request to be merged quickly and without additional clarification requests.
+3. Commits must be accompanied by meaningful commit messages.
+4. PRs which include bug fixing, must be accompanied with step-by-step description of how to reproduce the bug.
+3. PRs which include new logic or new features must be submitted along with:
+* Unit/integration test coverage (we will be releasing more information on writing test coverage in the near future).
+* Proposed [documentation](http://devdocs.magento.com) update. Documentation contributions can be submitted [here](https://github.com/magento/devdocs).
+4. For large features or changes, please [open an issue](https://github.com/magento/magento2/issues) and discuss first. This may prevent duplicate or unnecessary effort, and it may gain you some additional contributors.
+5. All automated tests are passed successfully (all builds on [Travis CI](https://travis-ci.org/magento/magento2) must be green).
 
-**Do I need to follow all requirements of the contribution process?**
+## Contribution process
 
-Yes. We strongly encourage that you follow the requirements as stated, before submitting your code or patch for Magento 2 development team's review. Properly submitted contributions will help the Magento 2 development team to quickly assess your contribution and incorporate it into the Magento 2 project if deemed beneficial.
-
-**Do you accept all contributions?**
+If you are a new GitHub user, we recommend that you create your own [free github account](https://github.com/signup/free). By doing that, you will be able to collaborate with the Magento 2 development team, “fork” the Magento 2 project and be able to easily send “pull requests”.
 
-Not all contributions will be used or incorporated into the code for the project. The decision to incorporate the code or not is at the discretion of the Magento 2 development team.
+1. Search current [listed issues](https://github.com/magento/magento2/issues) (open or closed) for similar proposals of intended contribution before starting work on a new contribution.
+2. Review the [Contributor License Agreement](https://github.com/magento/magento2/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.html) if this is your first time contributing.
+3. Create and test your work.
+4. Fork the Magento 2 repository according to [Fork a repository instructions](http://devdocs.magento.com/guides/v1.0/contributor-guide/CONTRIBUTING.html#fork) and when you are ready to send us a pull request – follow [Create a pull request instructions](http://devdocs.magento.com/guides/v1.0/contributor-guide/CONTRIBUTING.html#pull_request).
+5. Once your contribution is received, Magento 2 development team will review the contribution and collaborate with you as needed to improve the quality of the contribution.
diff --git a/app/code/Magento/AdminNotification/Model/Resource/System/Message/Collection.php b/app/code/Magento/AdminNotification/Model/Resource/System/Message/Collection.php
index 230934526fbeda2cee4ff28447e809c5f76bdb73..ff450f7379266ac453299d12136b0617aabf26fc 100644
--- a/app/code/Magento/AdminNotification/Model/Resource/System/Message/Collection.php
+++ b/app/code/Magento/AdminNotification/Model/Resource/System/Message/Collection.php
@@ -22,7 +22,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Notification\MessageList $messageList
@@ -31,7 +31,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Notification\MessageList $messageList,
diff --git a/app/code/Magento/AdminNotification/composer.json b/app/code/Magento/AdminNotification/composer.json
index 888893761470f6d51491fa0b7d0f061f3d0ac09f..c535ad1fe7846192b0f5a61f77e5cb89559945ab 100644
--- a/app/code/Magento/AdminNotification/composer.json
+++ b/app/code/Magento/AdminNotification/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Authorization/Model/Acl/AclRetriever.php b/app/code/Magento/Authorization/Model/Acl/AclRetriever.php
index 3837a7babb2f375b5a418b8c2fd324ce6bc5377c..bbe4491d5cf8fe8c6fa5e51e9986e9838ddeb0d8 100644
--- a/app/code/Magento/Authorization/Model/Acl/AclRetriever.php
+++ b/app/code/Magento/Authorization/Model/Acl/AclRetriever.php
@@ -12,7 +12,7 @@ use Magento\Authorization\Model\UserContextInterface;
 use Magento\Framework\Acl\Builder as AclBuilder;
 use Magento\Framework\Exception\AuthorizationException;
 use Magento\Framework\Exception\LocalizedException;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Permission tree retriever
@@ -79,7 +79,7 @@ class AclRetriever
         } catch (AuthorizationException $e) {
             throw $e;
         } catch (\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             throw new LocalizedException(
                 'Error happened while getting a list of allowed resources. Check exception log for details.'
             );
diff --git a/app/code/Magento/Authorization/Model/Resource/Rules.php b/app/code/Magento/Authorization/Model/Resource/Rules.php
index e367b05e2cfb0122d80dc6693d56b2180ca9aed3..d1f16dbe54a44fe18d71d6cb440f3a89b06469ac 100644
--- a/app/code/Magento/Authorization/Model/Resource/Rules.php
+++ b/app/code/Magento/Authorization/Model/Resource/Rules.php
@@ -29,21 +29,21 @@ class Rules extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected $_aclBuilder;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
      * @param \Magento\Framework\App\Resource $resource
      * @param \Magento\Framework\Acl\Builder $aclBuilder
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Acl\RootResource $rootResource
      * @param \Magento\Framework\Acl\CacheInterface $aclCache
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
         \Magento\Framework\Acl\Builder $aclBuilder,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Acl\RootResource $rootResource,
         \Magento\Framework\Acl\CacheInterface $aclCache
     ) {
@@ -116,7 +116,7 @@ class Rules extends \Magento\Framework\Model\Resource\Db\AbstractDb
             throw $e;
         } catch (\Exception $e) {
             $adapter->rollBack();
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/Authorization/composer.json b/app/code/Magento/Authorization/composer.json
index 38c4e3fbde9c984ef50ef70c999f3ad85fc2ecc4..531bda8586eb3e1bd15077592b596c55010c8f5b 100644
--- a/app/code/Magento/Authorization/composer.json
+++ b/app/code/Magento/Authorization/composer.json
@@ -3,12 +3,12 @@
     "description": "Authorization module provides access to Magento ACL functionality.",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Backend/Block/Context.php b/app/code/Magento/Backend/Block/Context.php
index 4e7548cde61e93852f3420d1f4472ef694525c66..988a0d22efd5834d255facbaaa49b22f15ae069c 100644
--- a/app/code/Magento/Backend/Block/Context.php
+++ b/app/code/Magento/Backend/Block/Context.php
@@ -32,7 +32,7 @@ class Context extends \Magento\Framework\View\Element\Context
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -55,7 +55,7 @@ class Context extends \Magento\Framework\View\Element\Context
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
diff --git a/app/code/Magento/Backend/Block/Template/Context.php b/app/code/Magento/Backend/Block/Template/Context.php
index 16e3bc65b5ace03f9df9c4202e435f47ec415840..b16288e76d23260d4858414930377074e99d5929 100644
--- a/app/code/Magento/Backend/Block/Template/Context.php
+++ b/app/code/Magento/Backend/Block/Template/Context.php
@@ -56,7 +56,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -89,7 +89,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
diff --git a/app/code/Magento/Backend/Block/Widget/Context.php b/app/code/Magento/Backend/Block/Widget/Context.php
index 7fd088cb03e0e9fa4a99883cd5277f8708b38b3d..549f433d313ec6faed1103ce2c92a87d2414f62c 100644
--- a/app/code/Magento/Backend/Block/Widget/Context.php
+++ b/app/code/Magento/Backend/Block/Widget/Context.php
@@ -39,7 +39,7 @@ class Context extends \Magento\Backend\Block\Template\Context
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -74,7 +74,7 @@ class Context extends \Magento\Backend\Block\Template\Context
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php
index c20d77945b32f266821d4806c5e3fd47537769b2..076ff34ceda090634c3a3f4b3685ddbd81b140e1 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php
@@ -80,7 +80,7 @@ class Currency extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstra
      */
     public function render(\Magento\Framework\Object $row)
     {
-        if ($data = (string)$row->getData($this->getColumn()->getIndex())) {
+        if ($data = (string)$this->_getValue($row)) {
             $currency_code = $this->_getCurrencyCode($row);
             $data = floatval($data) * $this->_getRate($row);
             $sign = (bool)(int)$this->getColumn()->getShowNumberSign() && $data > 0 ? '+' : '';
diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php
index f2b3b0381aa89e9647822da5d0ccd1e7fd7f07a1..f9524ada7933e530f668c23f6ffcb667c41f6276 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Date.php
@@ -45,7 +45,7 @@ class Date extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRe
                         \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_MEDIUM
                     );
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                 }
             }
             $format = self::$_format;
diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Datetime.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Datetime.php
index 3ac62cee213c872769e703bc664a9bdabc649eb9..8b6e3f124258df18fe22aad82112be3e0d1d6d06 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Datetime.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Datetime.php
@@ -32,7 +32,7 @@ class Datetime extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstra
                         \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_MEDIUM
                     );
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                 }
             }
             $format = self::$_format;
diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Price.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Price.php
index e140c79586007d671ff745df6ee490a0af96d4eb..8dc712981ef87ecc8dcca2282ba7ca1076c45577 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Price.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Price.php
@@ -48,7 +48,7 @@ class Price extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractR
      */
     public function render(\Magento\Framework\Object $row)
     {
-        if ($data = $row->getData($this->getColumn()->getIndex())) {
+        if ($data = $this->_getValue($row)) {
             $currencyCode = $this->_getCurrencyCode($row);
 
             if (!$currencyCode) {
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/Tunnel.php b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/Tunnel.php
index 5a2785e0e74f98972d2ee859ca8775b59b67b628..94752f8e1e4ed20dcc93721a507e9e3c80bdd0f3 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/Tunnel.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/Dashboard/Tunnel.php
@@ -68,7 +68,7 @@ class Tunnel extends \Magento\Backend\Controller\Adminhtml\Dashboard
                             ->setContents($response->getBody());
                         return $resultRaw;
                     } catch (\Exception $e) {
-                        $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                        $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                         $error = __('see error log for details');
                         $httpCode = 503;
                     }
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Status.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Status.php
index f3133d990c93cfcc0717ad436030a3f8b004c78b..fa14e28e5c50ece20078464fae5f3b9160571b49 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Status.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Status.php
@@ -79,8 +79,8 @@ class Status extends \Magento\Backend\Controller\Adminhtml\System\Config\System\
                         ) && $flagData['timeout_reached'])
                         ) {
                             $this->_objectManager->get(
-                                'Magento\Framework\Logger'
-                            )->logException(
+                                'Psr\Log\LoggerInterface'
+                            )->critical(
                                 new \Magento\Framework\Exception(
                                     __('The timeout limit for response from synchronize process was reached.')
                                 )
diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Synchronize.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Synchronize.php
index b2b6c0fff5e5d33149b9a91c8b5296ed486c38a9..f7f1615bf25930afff0cda3e48f448b4bc20934b 100644
--- a/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Synchronize.php
+++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Config/System/Storage/Synchronize.php
@@ -43,7 +43,7 @@ class Synchronize extends \Magento\Backend\Controller\Adminhtml\System\Config\Sy
         try {
             $this->_getSyncSingleton()->synchronize($storage);
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $flag->passError($e);
         }
 
diff --git a/app/code/Magento/Backend/Model/Menu.php b/app/code/Magento/Backend/Model/Menu.php
index f70c0b698268be380c08c10d90d8c203d5006ad0..79fd68d8edb748d562e303e84cac0a13f49890b1 100644
--- a/app/code/Magento/Backend/Model/Menu.php
+++ b/app/code/Magento/Backend/Model/Menu.php
@@ -9,11 +9,6 @@ namespace Magento\Backend\Model;
  */
 class Menu extends \ArrayObject
 {
-    /**
-     * Name of special logger key for debugging building menu
-     */
-    const LOGGER_KEY = 'menu-debug';
-
     /**
      * Path in tree structure
      *
@@ -22,15 +17,15 @@ class Menu extends \ArrayObject
     protected $_path = '';
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param string $pathInMenuStructure
      */
-    public function __construct(\Magento\Framework\Logger $logger, $pathInMenuStructure = '')
+    public function __construct(\Psr\Log\LoggerInterface $logger, $pathInMenuStructure = '')
     {
         if ($pathInMenuStructure) {
             $this->_path = $pathInMenuStructure . '/';
@@ -60,9 +55,8 @@ class Menu extends \ArrayObject
             $index = intval($index);
             if (!isset($this[$index])) {
                 $this->offsetSet($index, $item);
-                $this->_logger->logDebug(
-                    sprintf('Add of item with id %s was processed', $item->getId()),
-                    self::LOGGER_KEY
+                $this->_logger->info(
+                    sprintf('Add of item with id %s was processed', $item->getId())
                 );
             } else {
                 $this->add($item, $parentId, $index + 1);
@@ -126,9 +120,8 @@ class Menu extends \ArrayObject
             if ($item->getId() == $itemId) {
                 unset($this[$key]);
                 $result = true;
-                $this->_logger->logDebug(
-                    sprintf('Remove on item with id %s was processed', $item->getId()),
-                    self::LOGGER_KEY
+                $this->_logger->info(
+                    sprintf('Remove on item with id %s was processed', $item->getId())
                 );
                 break;
             }
diff --git a/app/code/Magento/Backend/Model/Menu/AbstractDirector.php b/app/code/Magento/Backend/Model/Menu/AbstractDirector.php
index f00a30085e076ea3e7eaf00a33f0a3debab49a3e..fa434a36aa8f40faae405461ac5d824dd05f93eb 100644
--- a/app/code/Magento/Backend/Model/Menu/AbstractDirector.php
+++ b/app/code/Magento/Backend/Model/Menu/AbstractDirector.php
@@ -25,12 +25,12 @@ abstract class AbstractDirector
      *
      * @param array $config
      * @param \Magento\Backend\Model\Menu\Builder $builder
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @return void
      */
     abstract public function direct(
         array $config,
         \Magento\Backend\Model\Menu\Builder $builder,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     );
 }
diff --git a/app/code/Magento/Backend/Model/Menu/Config.php b/app/code/Magento/Backend/Model/Menu/Config.php
index 0a023244a00a26b9dcc95001c8cded7dde77f212..19f9c2526a713f52182c179b593d560fdaa661e6 100644
--- a/app/code/Magento/Backend/Model/Menu/Config.php
+++ b/app/code/Magento/Backend/Model/Menu/Config.php
@@ -33,7 +33,7 @@ class Config
     protected $_menu;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -64,7 +64,7 @@ class Config
      * @param \Magento\Backend\Model\Menu\Config\Reader $configReader
      * @param \Magento\Framework\App\Cache\Type\Config $configCacheType
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Framework\App\State $appState
      */
@@ -75,7 +75,7 @@ class Config
         \Magento\Backend\Model\Menu\Config\Reader $configReader,
         \Magento\Framework\App\Cache\Type\Config $configCacheType,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Framework\App\State $appState
     ) {
@@ -101,21 +101,17 @@ class Config
      */
     public function getMenu()
     {
-        if ($this->_scopeConfig->getValue('dev/log/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) {
-            $this->_logger->addStreamLog(\Magento\Backend\Model\Menu::LOGGER_KEY);
-        }
-
         try {
             $this->_initMenu();
             return $this->_menu;
         } catch (\InvalidArgumentException $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw $e;
         } catch (\BadMethodCallException $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw $e;
         } catch (\OutOfRangeException $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw $e;
         } catch (\Exception $e) {
             throw $e;
diff --git a/app/code/Magento/Backend/Model/Menu/Director/Director.php b/app/code/Magento/Backend/Model/Menu/Director/Director.php
index dc1854a5ddf0ab4ce76734dcf1eaf233499c5278..0d77330ecb0c501159def7be2ab3eb403d265cde 100644
--- a/app/code/Magento/Backend/Model/Menu/Director/Director.php
+++ b/app/code/Magento/Backend/Model/Menu/Director/Director.php
@@ -17,16 +17,15 @@ class Director extends \Magento\Backend\Model\Menu\AbstractDirector
      * Get command object
      *
      * @param array $data command params
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @return \Magento\Backend\Model\Menu\Builder\AbstractCommand
      */
     protected function _getCommand($data, $logger)
     {
         $command = $this->_commandFactory->create($data['type'], ['data' => $data]);
         if (isset($this->_messagePatterns[$data['type']])) {
-            $logger->logDebug(
-                sprintf($this->_messagePatterns[$data['type']], $command->getId()),
-                \Magento\Backend\Model\Menu::LOGGER_KEY
+            $logger->info(
+                sprintf($this->_messagePatterns[$data['type']], $command->getId())
             );
         }
         return $command;
@@ -37,10 +36,10 @@ class Director extends \Magento\Backend\Model\Menu\AbstractDirector
      *
      * @param array $config
      * @param \Magento\Backend\Model\Menu\Builder $builder
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @return void
      */
-    public function direct(array $config, \Magento\Backend\Model\Menu\Builder $builder, \Magento\Framework\Logger $logger)
+    public function direct(array $config, \Magento\Backend\Model\Menu\Builder $builder, \Psr\Log\LoggerInterface $logger)
     {
         foreach ($config as $data) {
             $builder->processCommand($this->_getCommand($data, $logger));
diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json
index 53c2f7f28212d0f9f043dc9bcc3fbb1600ab92cd..aeec76291c95bb55f57092e3af7e1356e73ca907 100644
--- a/app/code/Magento/Backend/composer.json
+++ b/app/code/Magento/Backend/composer.json
@@ -3,26 +3,26 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-cron": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-reports": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-user": "0.42.0-beta1",
-        "magento/module-backup": "0.42.0-beta1",
-        "magento/module-email": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-translation": "0.42.0-beta1",
-        "magento/module-require-js": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-cron": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-reports": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-user": "0.42.0-beta2",
+        "magento/module-backup": "0.42.0-beta2",
+        "magento/module-email": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-translation": "0.42.0-beta2",
+        "magento/module-require-js": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml
index 46b73ca4621c457d523053720a5777210fb95c19..888b0855bb97285f88a55527c05950bc75aa0321 100644
--- a/app/code/Magento/Backend/etc/adminhtml/system.xml
+++ b/app/code/Magento/Backend/etc/adminhtml/system.xml
@@ -193,23 +193,6 @@
                     <comment>Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.</comment>
                 </field>
             </group>
-            <group id="log" translate="label" type="text" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1">
-                <label>Log Settings</label>
-                <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
-                    <label>Enabled</label>
-                    <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
-                </field>
-                <field id="file" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
-                    <label>System Log File Name</label>
-                    <backend_model>Magento\Backend\Model\Config\Backend\Filename</backend_model>
-                    <comment>Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log</comment>
-                </field>
-                <field id="exception_file" translate="label comment" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
-                    <label>Exceptions Log File Name</label>
-                    <backend_model>Magento\Backend\Model\Config\Backend\Filename</backend_model>
-                    <comment>Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log</comment>
-                </field>
-            </group>
             <group id="js" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
                 <label>JavaScript Settings</label>
                 <field id="merge_files" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
diff --git a/app/code/Magento/Backend/i18n/de_DE.csv b/app/code/Magento/Backend/i18n/de_DE.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/de_DE.csv
+++ b/app/code/Magento/Backend/i18n/de_DE.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/en_US.csv
+++ b/app/code/Magento/Backend/i18n/en_US.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/es_ES.csv b/app/code/Magento/Backend/i18n/es_ES.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/es_ES.csv
+++ b/app/code/Magento/Backend/i18n/es_ES.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/fr_FR.csv b/app/code/Magento/Backend/i18n/fr_FR.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/fr_FR.csv
+++ b/app/code/Magento/Backend/i18n/fr_FR.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/nl_NL.csv b/app/code/Magento/Backend/i18n/nl_NL.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/nl_NL.csv
+++ b/app/code/Magento/Backend/i18n/nl_NL.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/pt_BR.csv b/app/code/Magento/Backend/i18n/pt_BR.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/pt_BR.csv
+++ b/app/code/Magento/Backend/i18n/pt_BR.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backend/i18n/zh_CN.csv b/app/code/Magento/Backend/i18n/zh_CN.csv
index 7a956dbcdcfac8a2a273978a7de9d18777128b48..9e12e495d09b79041066b3d27581470edcc2c62c 100644
--- a/app/code/Magento/Backend/i18n/zh_CN.csv
+++ b/app/code/Magento/Backend/i18n/zh_CN.csv
@@ -504,7 +504,7 @@ Developer,Developer
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."
 "Log Settings","Log Settings"
 "System Log File Name","System Log File Name"
-"Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log","Logging from \Magento\Framework\Logger. File is located in {{base_dir}}/var/log"
+"Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log","Logging from \Psr\Log\LoggerInterface. File is located in {{base_dir}}/var/log"
 "Exceptions Log File Name","Exceptions Log File Name"
 "JavaScript Settings","JavaScript Settings"
 "Merge JavaScript Files","Merge JavaScript Files"
diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php
index ebcf25e8637e9123a7718b46b6cd51ce19ffc9a8..d594ed0907050804b77eb590e5d8ff406826572c 100644
--- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php
+++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Create.php
@@ -86,10 +86,10 @@ class Create extends \Magento\Backup\Controller\Adminhtml\Index
         } catch (\Magento\Framework\Backup\Exception\NotEnoughFreeSpace $e) {
             $errorMessage = __('You need more free space to create a backup.');
         } catch (\Magento\Framework\Backup\Exception\NotEnoughPermissions $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->log($e->getMessage());
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->info($e->getMessage());
             $errorMessage = __('You need more permissions to create a backup.');
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->log($e->getMessage());
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->info($e->getMessage());
             $errorMessage = __('Something went wrong creating the backup.');
         }
 
diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php
index 86c130e00757f6508d88d289715df9e9df959208..20723783b18fa94bffba7210ffaebb10c8aa358c 100644
--- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php
+++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Rollback.php
@@ -122,10 +122,10 @@ class Rollback extends \Magento\Backup\Controller\Adminhtml\Index
         } catch (\Magento\Framework\Backup\Exception\FtpValidationFailed $e) {
             $errorMsg = __('Failed to validate FTP');
         } catch (\Magento\Framework\Backup\Exception\NotEnoughPermissions $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->log($e->getMessage());
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->info($e->getMessage());
             $errorMsg = __('Not enough permissions to perform rollback.');
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->log($e->getMessage());
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->info($e->getMessage());
             $errorMsg = __('Failed to rollback');
         }
 
diff --git a/app/code/Magento/Backup/Model/Observer.php b/app/code/Magento/Backup/Model/Observer.php
index 0e2d75bc06ec1079efa906dedad46ef6e46c89fe..c6e408ce4e9374eace22b210458cf17546ebfd88 100644
--- a/app/code/Magento/Backup/Model/Observer.php
+++ b/app/code/Magento/Backup/Model/Observer.php
@@ -43,7 +43,7 @@ class Observer
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -74,7 +74,7 @@ class Observer
     /**
      * @param \Magento\Backup\Helper\Data $backupData
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Backup\Factory $backupFactory
@@ -83,7 +83,7 @@ class Observer
     public function __construct(
         \Magento\Backup\Helper\Data $backupData,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Backup\Factory $backupFactory,
@@ -139,12 +139,12 @@ class Observer
 
             $backupManager->create();
             $message = $this->_backupData->getCreateSuccessMessageByType($type);
-            $this->_logger->log($message);
+            $this->_logger->info($message);
         } catch (\Exception $e) {
             $this->_errors[] = $e->getMessage();
             $this->_errors[] = $e->getTrace();
-            $this->_logger->log($e->getMessage(), \Zend_Log::ERR);
-            $this->_logger->logException($e);
+            $this->_logger->info($e->getMessage());
+            $this->_logger->critical($e);
         }
 
         if ($this->_scopeConfig->isSetFlag(self::XML_PATH_BACKUP_MAINTENANCE_MODE, ScopeInterface::SCOPE_STORE)) {
diff --git a/app/code/Magento/Backup/composer.json b/app/code/Magento/Backup/composer.json
index e942ee4651adbd4873ed87db0917d1cc0810bdb4..607d773f9484ff144461baaa870cf7b3497d0cf9 100644
--- a/app/code/Magento/Backup/composer.json
+++ b/app/code/Magento/Backup/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-cron": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-cron": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php
index d347baa277fbff8e0886253717e35265c18c915d..adcd9dd07f48b2e880acf372bd5ba2223c8dd53e 100644
--- a/app/code/Magento/Bundle/Model/Product/Type.php
+++ b/app/code/Magento/Bundle/Model/Product/Type.php
@@ -141,7 +141,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType
      * @param \Magento\Core\Helper\File\Storage\Database $fileStorageDb
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param ProductRepositoryInterface $productRepository
      * @param \Magento\Catalog\Helper\Product $catalogProduct
      * @param \Magento\Catalog\Helper\Data $catalogData
@@ -167,7 +167,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType
         \Magento\Core\Helper\File\Storage\Database $fileStorageDb,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         ProductRepositoryInterface $productRepository,
         \Magento\Catalog\Helper\Product $catalogProduct,
         \Magento\Catalog\Helper\Data $catalogData,
diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json
index 775e22220ac226e60ac3c935690ba5458f50c582..361d5902c7b7e9a2aa4853d9d09219d5a1ea1e1f 100644
--- a/app/code/Magento/Bundle/composer.json
+++ b/app/code/Magento/Bundle/composer.json
@@ -3,24 +3,24 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-catalog-rule": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-gift-message": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-webapi": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-catalog-rule": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-gift-message": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-webapi": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json
index 280c374d3137f3f089e98435c8fa334460da8017..a8d6ee4d23b55b7b0a8d98e71bdce238972a255a 100644
--- a/app/code/Magento/Captcha/composer.json
+++ b/app/code/Magento/Captcha/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Catalog/Block/Product/Context.php b/app/code/Magento/Catalog/Block/Product/Context.php
index 916e5c5fff6c076ee1fa0e2a2590682519daeb51..14ae9729f3e07a2cb2b74836acd29c191d32fe31 100644
--- a/app/code/Magento/Catalog/Block/Product/Context.php
+++ b/app/code/Magento/Catalog/Block/Product/Context.php
@@ -83,7 +83,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -122,7 +122,7 @@ class Context extends \Magento\Framework\View\Element\Template\Context
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php
index f335af5a99dfe1c4f763a36f2606d42bfacd238e..8b4683d0fb483a6f351624dc54432e35f8626413 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Move.php
@@ -18,7 +18,7 @@ class Move extends \Magento\Catalog\Controller\Adminhtml\Category
     protected $layoutFactory;
 
     /**
-     * @var \Magento\Framework\Logger $logger
+     * @var \Psr\Log\LoggerInterface $logger
      */
     protected $logger;
 
@@ -27,14 +27,14 @@ class Move extends \Magento\Catalog\Controller\Adminhtml\Category
      * @param \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory
      * @param \Magento\Framework\Controller\Result\JSONFactory $resultJsonFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory,
-     * @param \Magento\Framework\Logger $logger,
+     * @param \Psr\Log\LoggerInterface $logger,
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory,
         \Magento\Framework\Controller\Result\JSONFactory $resultJsonFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         parent::__construct($context, $resultRedirectFactory);
         $this->resultJsonFactory = $resultJsonFactory;
@@ -77,7 +77,7 @@ class Move extends \Magento\Catalog\Controller\Adminhtml\Category
         } catch (\Exception $e) {
             $error = true;
             $this->messageManager->addError(__('There was a category move error.'));
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
 
         if (!$error) {
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php
index 511f9a701d5413f014ec7d9a7814e147da45c1a0..0f712c177e24df5cc0fb838f806fc5c21450027b 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php
@@ -8,7 +8,7 @@ namespace Magento\Catalog\Controller\Adminhtml\Product;
 use Magento\Catalog\Model\ProductFactory;
 use Magento\Cms\Model\Wysiwyg as WysiwygModel;
 use Magento\Framework\App\RequestInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Registry;
 
 class Builder
@@ -19,7 +19,7 @@ class Builder
     protected $productFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -75,7 +75,7 @@ class Builder
                 $product->load($productId);
             } catch (\Exception $e) {
                 $product->setTypeId(\Magento\Catalog\Model\Product\Type::DEFAULT_TYPE);
-                $this->logger->logException($e);
+                $this->logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
index 827d1bdce796135622498ee9a265b5e50de0db80..618b90846c50111866dd0c8828e64c579a1c6f28 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
@@ -53,7 +53,7 @@ class Duplicate extends \Magento\Catalog\Controller\Adminhtml\Product
             $this->messageManager->addSuccess(__('You duplicated the product.'));
             $resultRedirect->setPath('catalog/*/edit', ['_current' => true, 'id' => $newProduct->getId()]);
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError($e->getMessage());
             $resultRedirect->setPath('catalog/*/edit', ['_current' => true]);
         }
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
index 3e55766a835c5dd0e8519a187a6366a5b0a96643..7dc0df9dbaee5e1e6011651c38c978987a4f2cd2 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
@@ -116,7 +116,7 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product
                 $this->_session->setProductData($data);
                 $redirectBack = $productId ? true : 'new';
             } catch (\Exception $e) {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->messageManager->addError($e->getMessage());
                 $this->_session->setProductData($data);
                 $redirectBack = $productId ? true : 'new';
diff --git a/app/code/Magento/Catalog/Controller/Category/View.php b/app/code/Magento/Catalog/Controller/Category/View.php
index 4e9df866610649b231ef106eb50288e8a347b981..d6db2447de5f1313addfb6fe498ede24f8c234fd 100644
--- a/app/code/Magento/Catalog/Controller/Category/View.php
+++ b/app/code/Magento/Catalog/Controller/Category/View.php
@@ -123,7 +123,7 @@ class View extends \Magento\Framework\App\Action\Action
                 ['category' => $category, 'controller_action' => $this]
             );
         } catch (\Magento\Framework\Model\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             return false;
         }
 
diff --git a/app/code/Magento/Catalog/Controller/Product/View.php b/app/code/Magento/Catalog/Controller/Product/View.php
index 3f36fe958a42cb6acc37fe913fc973f6eba7e37a..de750fd1151475b76f5dde70be25546a76f0577c 100644
--- a/app/code/Magento/Catalog/Controller/Product/View.php
+++ b/app/code/Magento/Catalog/Controller/Product/View.php
@@ -111,7 +111,7 @@ class View extends \Magento\Catalog\Controller\Product
             if ($e->getCode() == $this->viewHelper->ERR_NO_PRODUCT_LOADED) {
                 return $this->noProductRedirect();
             } else {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $resultForward = $this->resultForwardFactory->create();
                 $resultForward->forward('noroute');
                 return $resultForward;
diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php
index 9388d17fda737f059b1bcd641b83a2e8be2bddb0..e232b7280a7939922ecf58bc9ae1cf269205909b 100644
--- a/app/code/Magento/Catalog/Helper/Image.php
+++ b/app/code/Magento/Catalog/Helper/Image.php
@@ -417,7 +417,7 @@ class Image extends AbstractHelper
         try {
             $url = $this->_assetRepo->getUrl($this->getPlaceholder());
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             $url = $this->_urlBuilder->getUrl('', ['_direct' => 'core/index/notFound']);
         }
         return $url;
diff --git a/app/code/Magento/Catalog/Helper/Product.php b/app/code/Magento/Catalog/Helper/Product.php
index 4503f58d1ec836ff45af7eac63b5631b4450913a..b26f922a2abffcc00015da45b00f4bf912171f2a 100644
--- a/app/code/Magento/Catalog/Helper/Product.php
+++ b/app/code/Magento/Catalog/Helper/Product.php
@@ -448,7 +448,7 @@ class Product extends \Magento\Core\Helper\Url
                 ['product' => $product, 'controller_action' => $controller]
             );
         } catch (\Magento\Framework\Model\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return false;
         }
 
diff --git a/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php b/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php
index 52473fe4834d131a60f06332727b0e9b9b4b1965..e029df6c439b40a9ada97050ac241801e300d2fa 100644
--- a/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php
+++ b/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php
@@ -304,7 +304,7 @@ class Indexer extends \Magento\Framework\App\Helper\AbstractHelper
                     $attribute->getBackend();
                     $this->_attributes[$attributeCode] = $attribute;
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                 }
             }
         }
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 4ab260e6e4cf653bda4bfa7de18477398303b107..2b3267239255e5f47ef4e720da1deb5d7a2b602b 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -34,19 +34,19 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     protected $_fileUploaderFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
      * Construct
      *
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Core\Model\File\UploaderFactory $fileUploaderFactory
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Core\Model\File\UploaderFactory $fileUploaderFactory
     ) {
@@ -93,7 +93,7 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
             $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
         } catch (\Exception $e) {
             if ($e->getCode() != \Magento\Core\Model\File\Uploader::TMP_NAME_EMPTY) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
         return $this;
diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
index 645c2437f5738507ef71b34a5fe85f52a408fecc..1b9fcdff10fe83b1b4c3526806c082f6f84678a9 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
@@ -123,7 +123,7 @@ abstract class AbstractType
     protected $_eventManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -164,7 +164,7 @@ abstract class AbstractType
      * @param \Magento\Core\Helper\File\Storage\Database $fileStorageDb
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param ProductRepositoryInterface $productRepository
      */
     public function __construct(
@@ -176,7 +176,7 @@ abstract class AbstractType
         \Magento\Core\Helper\File\Storage\Database $fileStorageDb,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         ProductRepositoryInterface $productRepository
     ) {
         $this->_catalogProductOption = $catalogProductOption;
@@ -1005,7 +1005,7 @@ abstract class AbstractType
         } catch (\Magento\Framework\Model\Exception $e) {
             $errors[] = $e->getMessages();
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             $errors[] = __('Something went wrong while processing the request.');
         }
 
diff --git a/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Collection.php b/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Collection.php
index bd7a18f5d3d4057e680e0331adec06d14fca9259..8f45e9274243814c0a448a4dad6a6d0ea480e63e 100644
--- a/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Category/Attribute/Collection.php
@@ -20,7 +20,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
@@ -30,7 +30,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Catalog/Model/Resource/Category/Flat/Collection.php b/app/code/Magento/Catalog/Model/Resource/Category/Flat/Collection.php
index 19cf99775d61330349b33ea5e847879a1b5c9b13..24ba5f442771cade8e2181070ddb6d9f5c230889 100644
--- a/app/code/Magento/Catalog/Model/Resource/Category/Flat/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Category/Flat/Collection.php
@@ -9,7 +9,7 @@ use Magento\Core\Model\EntityFactory;
 use Magento\Framework\Event\ManagerInterface;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 use Magento\Framework\Model\Resource\Db\AbstractDb;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Store\Model\StoreManagerInterface;
 
 /**
diff --git a/app/code/Magento/Catalog/Model/Resource/Collection/AbstractCollection.php b/app/code/Magento/Catalog/Model/Resource/Collection/AbstractCollection.php
index a70a1aa239ccd74c3fec2f58800baea9ffa77068..996f805d3efc8a9d02a4b7b8b65a6390877df4b5 100644
--- a/app/code/Magento/Catalog/Model/Resource/Collection/AbstractCollection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Collection/AbstractCollection.php
@@ -28,7 +28,7 @@ class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\AbstractCo
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -43,7 +43,7 @@ class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\AbstractCo
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Attribute/Collection.php b/app/code/Magento/Catalog/Model/Resource/Product/Attribute/Collection.php
index 5650e22e54352787fd69a44d4abc6e6f8296977c..6183326f86b90f88dc33083784a261879ccf9d32 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Attribute/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Attribute/Collection.php
@@ -18,7 +18,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
@@ -28,7 +28,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Collection.php b/app/code/Magento/Catalog/Model/Resource/Product/Collection.php
index 0d5d6565704a0aba82aefae03ef8eefe785bca68..73b7c3cb603b3fc7e3ea58a2385c36c76c727d14 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Collection.php
@@ -248,7 +248,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -272,7 +272,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Collection\AbstractColl
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Compare/Item/Collection.php b/app/code/Magento/Catalog/Model/Resource/Product/Compare/Item/Collection.php
index 46e9df4738f189c7e4958a56c7ef8959b0fbc8bb..c82e9ed4d6ffc0b1149529bd2bdf48dbebea3029 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Compare/Item/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Compare/Item/Collection.php
@@ -49,7 +49,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -75,7 +75,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Option/Collection.php b/app/code/Magento/Catalog/Model/Resource/Product/Option/Collection.php
index 645ab02c2ad436b3fb782fd9aaf532ca481164d4..550aa2c1ae5e0e99e76eec0158dd640ec8ebddab 100644
--- a/app/code/Magento/Catalog/Model/Resource/Product/Option/Collection.php
+++ b/app/code/Magento/Catalog/Model/Resource/Product/Option/Collection.php
@@ -27,7 +27,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory $optionValueCollectionFactory
@@ -37,7 +37,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory $optionValueCollectionFactory,
diff --git a/app/code/Magento/Catalog/Model/Resource/Url.php b/app/code/Magento/Catalog/Model/Resource/Url.php
index d59abd1efead5d8b18e5f8a0d656c41787820052..eacf7eceddc10b7d91f891de3c59a5f33d3eaa98 100644
--- a/app/code/Magento/Catalog/Model/Resource/Url.php
+++ b/app/code/Magento/Catalog/Model/Resource/Url.php
@@ -49,7 +49,7 @@ class Url extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected $_rootChildrenIds = [];
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -92,7 +92,7 @@ class Url extends \Magento\Framework\Model\Resource\Db\AbstractDb
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param Product $productResource
      * @param \Magento\Catalog\Model\Category $catalogCategory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
@@ -100,7 +100,7 @@ class Url extends \Magento\Framework\Model\Resource\Db\AbstractDb
         \Magento\Eav\Model\Config $eavConfig,
         Product $productResource,
         \Magento\Catalog\Model\Category $catalogCategory,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->_storeManager = $storeManager;
         $this->_eavConfig = $eavConfig;
diff --git a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php
index ceaaba2fcc5c9fe62450ed74bb017b0552c590c5..9b9feb713dcb206731ff1617e52832eedd0708eb 100644
--- a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php
+++ b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php
@@ -33,7 +33,7 @@ class FinalPriceBox extends BasePriceBox
             /** @var MsrpPrice $msrpPriceType */
             $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price');
         } catch (\InvalidArgumentException $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return $this->wrapResult($result);
         }
 
diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json
index 2fd878e153020d36d947e7df9098c70e305aee51..fe448355f37bf47235b2a013f049b70c559f9755 100644
--- a/app/code/Magento/Catalog/composer.json
+++ b/app/code/Magento/Catalog/composer.json
@@ -3,33 +3,33 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-log": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-msrp": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-catalog-rule": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-product-alert": "0.42.0-beta1",
-        "magento/module-url-rewrite": "0.42.0-beta1",
-        "magento/module-catalog-url-rewrite": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-log": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-msrp": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-catalog-rule": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-product-alert": "0.42.0-beta2",
+        "magento/module-url-rewrite": "0.42.0-beta2",
+        "magento/module-catalog-url-rewrite": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Catalog/i18n/de_DE.csv b/app/code/Magento/Catalog/i18n/de_DE.csv
index 8b0df7438ce015d65e4ac23080bbc9c5a67408c3..ecbd2cb02116bf9af5c3f6ac5bae02811a89a110 100644
--- a/app/code/Magento/Catalog/i18n/de_DE.csv
+++ b/app/code/Magento/Catalog/i18n/de_DE.csv
@@ -14,7 +14,7 @@ Qty,Qty
 Action,Aktion
 Reset,Zurücksetzen
 Edit,Bearbeiten
-"Add to Cart","Zum Warenkobrn hinzufügen"
+"Add to Cart","Zum Warenkorb hinzufügen"
 "Images (.gif, .jpg, .png)","Images (.gif, .jpg, .png)"
 "First Name",Vorname
 "Last Name","Letzter Name"
diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
index 1f8ac93fd8125187b5be450ce667ea0b23758705..c3d0f1d794394fbc36ed203b7717865a47aa54c5 100644
--- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -139,7 +139,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
     protected $_exportConfig;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -200,7 +200,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
      * @param \Magento\Eav\Model\Config $config
      * @param \Magento\Framework\App\Resource $resource
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Catalog\Model\Resource\Product\Collection $collection
      * @param \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig
      * @param \Magento\Catalog\Model\Resource\ProductFactory $productFactory
@@ -218,7 +218,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
         \Magento\Eav\Model\Config $config,
         \Magento\Framework\App\Resource $resource,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Catalog\Model\Resource\Product\Collection $collection,
         \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig,
         \Magento\Catalog\Model\Resource\ProductFactory $productFactory,
@@ -1105,7 +1105,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
                 }
             }
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return $exportData;
     }
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
index 8f59ba1aa57c22299af9ab6cc03c2c550674e161..60bcd0528cf208056d53fbd0b3f43c34fa7f8bd1 100644
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
@@ -481,7 +481,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     protected $indexerRegistry;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     private $_logger;
 
@@ -520,7 +520,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      * @param \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry
      * @param array $data
      * @throws \Magento\Framework\Model\Exception
@@ -555,7 +555,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
         \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Framework\Stdlib\DateTime $dateTime,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Indexer\Model\IndexerRegistry $indexerRegistry,
         array $data = []
     ) {
@@ -1102,7 +1102,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
                             if ($linkedId == null) {
                                 // Import file links to a SKU which is skipped for some reason, which leads to a "NULL"
                                 // link causing fatal errors.
-                                $this->_logger->logException(
+                                $this->_logger->critical(
                                     new \Exception(
                                         sprintf(
                                             'WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, ' .
diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json
index 597c28e83ed520974fd09aea6a6321b1f32fa13f..0c8868a542cf707b51e007b4316050a37374a03f 100644
--- a/app/code/Magento/CatalogImportExport/composer.json
+++ b/app/code/Magento/CatalogImportExport/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "ext-ctype": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogInventory/Model/Resource/Stock/Item/StockItemCriteriaMapper.php b/app/code/Magento/CatalogInventory/Model/Resource/Stock/Item/StockItemCriteriaMapper.php
index 14c56cf114085b9c5f1c98c59c959e577511d05d..5c67e12811ebfadcb3eace8a1d30c09b3d42b6dc 100644
--- a/app/code/Magento/CatalogInventory/Model/Resource/Stock/Item/StockItemCriteriaMapper.php
+++ b/app/code/Magento/CatalogInventory/Model/Resource/Stock/Item/StockItemCriteriaMapper.php
@@ -10,7 +10,7 @@ use Magento\Framework\DB\MapperFactory;
 use Magento\Framework\DB\Select;
 use Magento\Framework\Data\ObjectFactory;
 use Magento\Store\Model\StoreManagerInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 
 /**
diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json
index 43819e95002d31386a60ebc4a48724253ff09a25..adcd06788b10bdbebff48141427c69d5ced7c870 100644
--- a/app/code/Magento/CatalogInventory/composer.json
+++ b/app/code/Magento/CatalogInventory/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/ApplyRules.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/ApplyRules.php
index 923ce9bd10c7065458991852e61424f325da1084..3d8804ff6d77cc68ee305af0436833c393325664 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/ApplyRules.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/ApplyRules.php
@@ -29,7 +29,7 @@ class ApplyRules extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog
                 $this->messageManager->addError($errorMessage . ' ' . $ruleJob->getError());
             }
         } catch (\Exception $e) {
-            $this->_objectManager->create('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->create('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError($errorMessage);
         }
         $this->_redirect('catalog_rule/*');
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php
index 440407f0e168c4d801690e95d32aa49076f0583a..fb7a1fc6b310e8b425ebcd8fd7070bc003ec1d25 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php
@@ -31,7 +31,7 @@ class Delete extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog
                 $this->messageManager->addError(
                     __('An error occurred while deleting the rule. Please review the log and try again.')
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->_redirect('catalog_rule/*/edit', ['id' => $this->getRequest()->getParam('id')]);
                 return;
             }
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
index 7124feaa8c9f7b7d319e2166f367a1c22d6f597a..70f07b81bfb0f588a93f95ad4779abc0036464ff 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
@@ -75,7 +75,7 @@ class Save extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog
                 $this->messageManager->addError(
                     __('An error occurred while saving the rule data. Please review the log and try again.')
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->_objectManager->get('Magento\Backend\Model\Session')->setPageData($data);
                 $this->_redirect('catalog_rule/*/edit', ['id' => $this->getRequest()->getParam('rule_id')]);
                 return;
diff --git a/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php b/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php
index 690e8e5a35cc2300d5b443c963abaf025e2d63dc..9c5cbbedb2b1e4f6841524aade16273b095f308e 100644
--- a/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php
+++ b/app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php
@@ -31,7 +31,7 @@ class IndexBuilder
     protected $ruleCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -75,7 +75,7 @@ class IndexBuilder
      * @param PriceCurrencyInterface $priceCurrency
      * @param \Magento\Framework\App\Resource $resource
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\Stdlib\DateTime $dateFormat
      * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime
@@ -87,7 +87,7 @@ class IndexBuilder
         PriceCurrencyInterface $priceCurrency,
         \Magento\Framework\App\Resource $resource,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\Stdlib\DateTime $dateFormat,
         \Magento\Framework\Stdlib\DateTime\DateTime $dateTime,
@@ -129,7 +129,7 @@ class IndexBuilder
         try {
             $this->doReindexByIds($ids);
         } catch (\Exception $e) {
-            $this->logException($e);
+            $this->critical($e);
             throw new CatalogRuleException($e->getMessage(), $e->getCode(), $e);
         }
     }
@@ -162,7 +162,7 @@ class IndexBuilder
         try {
             $this->doReindexFull();
         } catch (\Exception $e) {
-            $this->logException($e);
+            $this->critical($e);
             throw new CatalogRuleException($e->getMessage(), $e->getCode(), $e);
         }
     }
@@ -551,7 +551,7 @@ class IndexBuilder
     /**
      * @param int $websiteId
      * @param int|null $productId
-     * @return \Zend\Db\Adapter\Driver\StatementInterface|\Zend_Db_Statement_Interface
+     * @return \Zend_Db_Statement_Interface
      * @throws \Magento\Eav\Exception
      */
     protected function getRuleProductsStmt($websiteId, $productId = null)
@@ -691,8 +691,8 @@ class IndexBuilder
      * @param \Exception $e
      * @return void
      */
-    protected function logException($e)
+    protected function critical($e)
     {
-        $this->logger->logException($e);
+        $this->logger->critical($e);
     }
 }
diff --git a/app/code/Magento/CatalogRule/Model/Resource/Rule.php b/app/code/Magento/CatalogRule/Model/Resource/Rule.php
index edc600c5faa05c9faf75d09b5ffcedf8174f9ae4..8d2f50e3fd9f369fbd245e487b22c3d0e7ec73ac 100644
--- a/app/code/Magento/CatalogRule/Model/Resource/Rule.php
+++ b/app/code/Magento/CatalogRule/Model/Resource/Rule.php
@@ -22,7 +22,7 @@ class Rule extends \Magento\Rule\Model\Resource\AbstractResource
     const SECONDS_IN_DAY = 86400;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -96,7 +96,7 @@ class Rule extends \Magento\Rule\Model\Resource\AbstractResource
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\CatalogRule\Helper\Data $catalogRuleData
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
      * @param PriceCurrencyInterface $priceCurrency
      */
@@ -108,7 +108,7 @@ class Rule extends \Magento\Rule\Model\Resource\AbstractResource
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\CatalogRule\Helper\Data $catalogRuleData,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime $dateTime,
         PriceCurrencyInterface $priceCurrency
     ) {
diff --git a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
index 7511d2f5c0bf065478159504cf539b9ca14a44f6..cb8b7786232a33d0fbf98c848ec2a55f0d83ffe7 100644
--- a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
+++ b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php
@@ -8,26 +8,29 @@
  */
 namespace Magento\CatalogRule\Model\Rule\Condition;
 
+/**
+ * Class Product
+ */
 class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
 {
     /**
      * Validate product attribute value for condition
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
         $attrCode = $this->getAttribute();
         if ('category_ids' == $attrCode) {
-            return $this->validateAttribute($object->getAvailableInCategories());
+            return $this->validateAttribute($model->getAvailableInCategories());
         }
 
-        $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null;
-        $this->_setAttributeValue($object);
+        $oldAttrValue = $model->hasData($attrCode) ? $model->getData($attrCode) : null;
+        $this->_setAttributeValue($model);
 
-        $result = $this->validateAttribute($object->getData($this->getAttribute()));
-        $this->_restoreOldAttrValue($object, $oldAttrValue);
+        $result = $this->validateAttribute($model->getData($this->getAttribute()));
+        $this->_restoreOldAttrValue($model, $oldAttrValue);
 
         return (bool)$result;
     }
@@ -35,36 +38,36 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
     /**
      * Restore old attribute value
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @param mixed $oldAttrValue
      * @return void
      */
-    protected function _restoreOldAttrValue($object, $oldAttrValue)
+    protected function _restoreOldAttrValue(\Magento\Framework\Model\AbstractModel $model, $oldAttrValue)
     {
         $attrCode = $this->getAttribute();
         if (is_null($oldAttrValue)) {
-            $object->unsetData($attrCode);
+            $model->unsetData($attrCode);
         } else {
-            $object->setData($attrCode, $oldAttrValue);
+            $model->setData($attrCode, $oldAttrValue);
         }
     }
 
     /**
      * Set attribute value
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return $this
      */
-    protected function _setAttributeValue($object)
+    protected function _setAttributeValue(\Magento\Framework\Model\AbstractModel $model)
     {
-        $storeId = $object->getStoreId();
+        $storeId = $model->getStoreId();
         $defaultStoreId = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
 
-        if (!isset($this->_entityAttributeValues[$object->getId()])) {
+        if (!isset($this->_entityAttributeValues[$model->getId()])) {
             return $this;
         }
 
-        $productValues  = $this->_entityAttributeValues[$object->getId()];
+        $productValues  = $this->_entityAttributeValues[$model->getId()];
 
         if (!isset($productValues[$storeId]) && !isset($productValues[$defaultStoreId])) {
             return $this;
@@ -72,10 +75,11 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
 
         $value = isset($productValues[$storeId]) ? $productValues[$storeId] : $productValues[$defaultStoreId];
 
-        $value = $this->_prepareDatetimeValue($value, $object);
-        $value = $this->_prepareMultiselectValue($value, $object);
+        $value = $this->_prepareDatetimeValue($value, $model);
+        $value = $this->_prepareMultiselectValue($value, $model);
+
+        $model->setData($this->getAttribute(), $value);
 
-        $object->setData($this->getAttribute(), $value);
         return $this;
     }
 
@@ -83,15 +87,16 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
      * Prepare datetime attribute value
      *
      * @param mixed $value
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return mixed
      */
-    protected function _prepareDatetimeValue($value, $object)
+    protected function _prepareDatetimeValue($value, \Magento\Framework\Model\AbstractModel $model)
     {
-        $attribute = $object->getResource()->getAttribute($this->getAttribute());
+        $attribute = $model->getResource()->getAttribute($this->getAttribute());
         if ($attribute && $attribute->getBackendType() == 'datetime') {
             $value = strtotime($value);
         }
+
         return $value;
     }
 
@@ -99,15 +104,16 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
      * Prepare multiselect attribute value
      *
      * @param mixed $value
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return mixed
      */
-    protected function _prepareMultiselectValue($value, $object)
+    protected function _prepareMultiselectValue($value, \Magento\Framework\Model\AbstractModel $model)
     {
-        $attribute = $object->getResource()->getAttribute($this->getAttribute());
+        $attribute = $model->getResource()->getAttribute($this->getAttribute());
         if ($attribute && $attribute->getFrontendInput() == 'multiselect') {
             $value = strlen($value) ? explode(',', $value) : [];
         }
+
         return $value;
     }
 }
diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json
index 9716d337d0282e00f5daea313ad087b20a33c2a9..8f0d6f3203c38c48f87bd3c59e3b64f6b831e978 100644
--- a/app/code/Magento/CatalogRule/composer.json
+++ b/app/code/Magento/CatalogRule/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-rule": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-rule": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Advanced/Collection.php
index 397bef86191a79bf904e13ae69bf2789cd783793..f8d25720209b343b4a019b6ee49d117018737a7e 100644
--- a/app/code/Magento/CatalogSearch/Model/Resource/Advanced/Collection.php
+++ b/app/code/Magento/CatalogSearch/Model/Resource/Advanced/Collection.php
@@ -31,7 +31,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -56,7 +56,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Fulltext/Collection.php
index f20d6544bd44c4ee6f14cb2b191738ba02cf4a5d..3a6827063f78f6414f01bf7922ef4823cfd2ffe9 100644
--- a/app/code/Magento/CatalogSearch/Model/Resource/Fulltext/Collection.php
+++ b/app/code/Magento/CatalogSearch/Model/Resource/Fulltext/Collection.php
@@ -48,7 +48,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -75,7 +75,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
index b5c31a4afac4737b191f361c4099da331981b1fe..2880a05ef464257bd60d0ed4a06f13ec5f0880bb 100644
--- a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
+++ b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
@@ -34,7 +34,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection impl
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -59,7 +59,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection impl
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json
index 367e3b7be755efa78af64c38f42655f2861440d8..cfc250a47f094b384254204e8b4af046a881b2b5 100644
--- a/app/code/Magento/CatalogSearch/composer.json
+++ b/app/code/Magento/CatalogSearch/composer.json
@@ -3,21 +3,21 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-search": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-search": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogUrlRewrite/composer.json b/app/code/Magento/CatalogUrlRewrite/composer.json
index 7ea6b9012c9ac0ed01a8ed66eeede85eeb9978d9..14b53cbabdb0ee3732264eb7dbdf6c1925e7c4ee 100644
--- a/app/code/Magento/CatalogUrlRewrite/composer.json
+++ b/app/code/Magento/CatalogUrlRewrite/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-catalog-import-export": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-url-rewrite": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-catalog-import-export": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-url-rewrite": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CatalogWidget/composer.json b/app/code/Magento/CatalogWidget/composer.json
index 9fd0e887d4f7ff0e31f07a7d387b7bc31e6ce2a7..9d078bb6a55ae2831e8fd91836a77fb220a4e3b5 100644
--- a/app/code/Magento/CatalogWidget/composer.json
+++ b/app/code/Magento/CatalogWidget/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-rule": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-rule": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Centinel/Controller/Adminhtml/Centinel/Index/ValidatePaymentData.php b/app/code/Magento/Centinel/Controller/Adminhtml/Centinel/Index/ValidatePaymentData.php
index 20a7d48d4ee87dc08e5799795bca68fde5197ff3..1cb27e4d7b623209aca3aa32d5981c9782d4c75b 100644
--- a/app/code/Magento/Centinel/Controller/Adminhtml/Centinel/Index/ValidatePaymentData.php
+++ b/app/code/Magento/Centinel/Controller/Adminhtml/Centinel/Index/ValidatePaymentData.php
@@ -27,7 +27,7 @@ class ValidatePaymentData extends \Magento\Centinel\Controller\Adminhtml\Centine
         } catch (\Magento\Framework\Model\Exception $e) {
             $result['message'] = $e->getMessage();
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $result['message'] = __('Validation failed.');
         }
         $this->getResponse()->representJson(
diff --git a/app/code/Magento/Centinel/Model/Api.php b/app/code/Magento/Centinel/Model/Api.php
index bb2b990ab7d0f0505ea92dd8312669bb16b64511..ccfe486b544d9562420752dae622251713c39b53 100644
--- a/app/code/Magento/Centinel/Model/Api.php
+++ b/app/code/Magento/Centinel/Model/Api.php
@@ -213,19 +213,17 @@ class Api extends \Magento\Framework\Object
     protected $_clientInstance = null;
 
     /**
-     * Log adapter factory
-     *
-     * @var \Magento\Framework\Logger\AdapterFactory
+     * @var \Psr\Log\LoggerInterface
      */
-    protected $_logFactory;
+    protected $logger;
 
     /**
-     * @param \Magento\Framework\Logger\AdapterFactory $logFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param array $data
      */
-    public function __construct(\Magento\Framework\Logger\AdapterFactory $logFactory, array $data = [])
+    public function __construct(\Psr\Log\LoggerInterface $logger, array $data = [])
     {
-        $this->_logFactory = $logFactory;
+        $this->logger = $logger;
         parent::__construct($data);
     }
 
@@ -419,13 +417,7 @@ class Api extends \Magento\Framework\Object
     protected function _debug($debugData)
     {
         if ($this->getDebugFlag()) {
-            $this->_logFactory->create(
-                ['fileName' => 'card_validation_3d_secure.log']
-            )->setFilterDataKeys(
-                $this->_debugReplacePrivateDataKeys
-            )->log(
-                $debugData
-            );
+            $this->logger->debug($debugData);
         }
     }
 }
diff --git a/app/code/Magento/Centinel/composer.json b/app/code/Magento/Centinel/composer.json
index 171bd6c6ccf6c84f1cd993c2ef3f9f123c9fd963..88add92445e432c7e47547b16ebf845df768b877 100644
--- a/app/code/Magento/Centinel/composer.json
+++ b/app/code/Magento/Centinel/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Checkout/Controller/Cart/Add.php b/app/code/Magento/Checkout/Controller/Cart/Add.php
index 69b4b42b53eefb1ca57298c411cc17c5007e2759..64abe026ff2f5ca522528018c6799712a9866d6c 100644
--- a/app/code/Magento/Checkout/Controller/Cart/Add.php
+++ b/app/code/Magento/Checkout/Controller/Cart/Add.php
@@ -134,7 +134,7 @@ class Add extends \Magento\Checkout\Controller\Cart
             }
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('We cannot add this item to your shopping cart'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_goBack();
         }
     }
diff --git a/app/code/Magento/Checkout/Controller/Cart/Addgroup.php b/app/code/Magento/Checkout/Controller/Cart/Addgroup.php
index 08607e38f063faa032cf3584f43bff4642730e9f..4911ebfd7ff64e081b92a13ce5f63c3bfe1bd7cd 100644
--- a/app/code/Magento/Checkout/Controller/Cart/Addgroup.php
+++ b/app/code/Magento/Checkout/Controller/Cart/Addgroup.php
@@ -31,7 +31,7 @@ class Addgroup extends \Magento\Checkout\Controller\Cart
                     }
                 } catch (\Exception $e) {
                     $this->messageManager->addException($e, __('We cannot add this item to your shopping cart'));
-                    $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                    $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                     $this->_goBack();
                 }
             }
diff --git a/app/code/Magento/Checkout/Controller/Cart/Configure.php b/app/code/Magento/Checkout/Controller/Cart/Configure.php
index 8731afaae8dceacde1558ca23c50fc1ed2921cf5..99fd6f1823074139888402d81fb75b845dc71566 100644
--- a/app/code/Magento/Checkout/Controller/Cart/Configure.php
+++ b/app/code/Magento/Checkout/Controller/Cart/Configure.php
@@ -71,7 +71,7 @@ class Configure extends \Magento\Checkout\Controller\Cart
             return $resultPage;
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We cannot configure the product.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_goBack();
             return;
         }
diff --git a/app/code/Magento/Checkout/Controller/Cart/CouponPost.php b/app/code/Magento/Checkout/Controller/Cart/CouponPost.php
index 346bb38a4a67b5a35a1ebad8a6884e9aa532416d..4bb72d37daeabe00bc6907396144f776127f1030 100644
--- a/app/code/Magento/Checkout/Controller/Cart/CouponPost.php
+++ b/app/code/Magento/Checkout/Controller/Cart/CouponPost.php
@@ -103,7 +103,7 @@ class CouponPost extends \Magento\Checkout\Controller\Cart
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We cannot apply the coupon code.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
 
         $this->_goBack();
diff --git a/app/code/Magento/Checkout/Controller/Cart/Delete.php b/app/code/Magento/Checkout/Controller/Cart/Delete.php
index 30540402d4ee00b15bb667c6ab78d162c9e7ef5e..0e57262dd25906dc536e44bec19857d3572bfc85 100644
--- a/app/code/Magento/Checkout/Controller/Cart/Delete.php
+++ b/app/code/Magento/Checkout/Controller/Cart/Delete.php
@@ -20,7 +20,7 @@ class Delete extends \Magento\Checkout\Controller\Cart
                 $this->cart->removeItem($id)->save();
             } catch (\Exception $e) {
                 $this->messageManager->addError(__('We cannot remove the item.'));
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             }
         }
         $defaultUrl = $this->_objectManager->create('Magento\Framework\UrlInterface')->getUrl('*/*');
diff --git a/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php b/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php
index 91b7c652ae3f6f7e3a04ed9a41cd39c3d5bfa309..7cc5528e1a445174f4c84da1cd71abed96b920a0 100644
--- a/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php
+++ b/app/code/Magento/Checkout/Controller/Cart/UpdateItemOptions.php
@@ -83,7 +83,7 @@ class UpdateItemOptions extends \Magento\Checkout\Controller\Cart
             }
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('We cannot update the item.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_goBack();
         }
         $this->_redirect('*/*');
diff --git a/app/code/Magento/Checkout/Controller/Cart/UpdatePost.php b/app/code/Magento/Checkout/Controller/Cart/UpdatePost.php
index 753e4ac69b0074edfb7660b62455afdf32fbb9d3..314755827a7594b2c6388f28439653e0e253124e 100644
--- a/app/code/Magento/Checkout/Controller/Cart/UpdatePost.php
+++ b/app/code/Magento/Checkout/Controller/Cart/UpdatePost.php
@@ -56,7 +56,7 @@ class UpdatePost extends \Magento\Checkout\Controller\Cart
             );
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('We cannot update the shopping cart.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 
diff --git a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php
index 18fe3c01b92b9fc56c0e51e4fefded5a2682f460..1fa75bfe5cc228f66932c8b8f013ce4dea1ca416 100644
--- a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php
+++ b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php
@@ -63,7 +63,7 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage
             $result['goto_section'] = 'payment';
             $result['update_section'] = ['name' => 'payment-method', 'html' => $this->_getPaymentMethodsHtml()];
         } catch (\Magento\Framework\Model\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_objectManager->get(
                 'Magento\Checkout\Helper\Data'
             )->sendPaymentFailedEmail(
@@ -91,7 +91,7 @@ class SaveOrder extends \Magento\Checkout\Controller\Onepage
                 $this->getOnepage()->getCheckout()->setUpdateSection(null);
             }
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_objectManager->get(
                 'Magento\Checkout\Helper\Data'
             )->sendPaymentFailedEmail(
diff --git a/app/code/Magento/Checkout/Controller/Onepage/SavePayment.php b/app/code/Magento/Checkout/Controller/Onepage/SavePayment.php
index 9e14aae22b385904533d3c2e98538400e65bee63..28e561ecaa53180d864a7f096191dcae93bbf3ce 100644
--- a/app/code/Magento/Checkout/Controller/Onepage/SavePayment.php
+++ b/app/code/Magento/Checkout/Controller/Onepage/SavePayment.php
@@ -56,7 +56,7 @@ class SavePayment extends \Magento\Checkout\Controller\Onepage
         } catch (\Magento\Framework\Model\Exception $e) {
             $result['error'] = $e->getMessage();
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $result['error'] = __('Unable to set Payment Method');
         }
         $this->getResponse()->representJson(
diff --git a/app/code/Magento/Checkout/Model/Type/Onepage.php b/app/code/Magento/Checkout/Model/Type/Onepage.php
index 00496f62cd207ab57452c9f26413ea8319a17a3f..ea05ce051088d4fc8a4e9b243353354a1af8cc99 100644
--- a/app/code/Magento/Checkout/Model/Type/Onepage.php
+++ b/app/code/Magento/Checkout/Model/Type/Onepage.php
@@ -51,7 +51,7 @@ class Onepage
     protected $_helper;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -168,7 +168,7 @@ class Onepage
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Checkout\Helper\Data $helper
      * @param \Magento\Customer\Model\Url $customerUrl
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Checkout\Model\Session $checkoutSession
      * @param \Magento\Customer\Model\Session $customerSession
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -196,7 +196,7 @@ class Onepage
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Checkout\Helper\Data $helper,
         \Magento\Customer\Model\Url $customerUrl,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Checkout\Model\Session $checkoutSession,
         \Magento\Customer\Model\Session $customerSession,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
@@ -925,7 +925,7 @@ class Onepage
             try {
                 $this->_involveNewCustomer();
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
@@ -953,7 +953,7 @@ class Onepage
                 try {
                     $this->orderSender->send($order);
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                 }
             }
 
diff --git a/app/code/Magento/Checkout/Service/V1/Address/Billing/WriteService.php b/app/code/Magento/Checkout/Service/V1/Address/Billing/WriteService.php
index 8cb870b3fbdb71084f2c0242190df22ceceb17c7..2a5e12158c6f3211718bf3b6e675e8d4c15ea988 100644
--- a/app/code/Magento/Checkout/Service/V1/Address/Billing/WriteService.php
+++ b/app/code/Magento/Checkout/Service/V1/Address/Billing/WriteService.php
@@ -9,7 +9,7 @@ use Magento\Checkout\Service\V1\Address\Validator;
 use Magento\Sales\Model\Quote\AddressFactory;
 use Magento\Sales\Model\QuoteRepository;
 use Magento\Framework\Exception\InputException;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /** Quote billing address write service object. */
 class WriteService implements WriteServiceInterface
@@ -105,7 +105,7 @@ class WriteService implements WriteServiceInterface
         try {
             $this->quoteRepository->save($quote);
         } catch (\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             throw new InputException('Unable to save address. Please, check input data.');
         }
         return $quote->getBillingAddress()->getId();
diff --git a/app/code/Magento/Checkout/Service/V1/Address/Shipping/WriteService.php b/app/code/Magento/Checkout/Service/V1/Address/Shipping/WriteService.php
index b58cfd6bab45626e9f21139443882f59f2983717..779e20019107a9a6174fe08f241649e1a451132e 100644
--- a/app/code/Magento/Checkout/Service/V1/Address/Shipping/WriteService.php
+++ b/app/code/Magento/Checkout/Service/V1/Address/Shipping/WriteService.php
@@ -6,7 +6,7 @@ namespace Magento\Checkout\Service\V1\Address\Shipping;
 
 use Magento\Framework\Exception\InputException;
 use Magento\Framework\Exception\NoSuchEntityException;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /** Quote shipping address write service object. */
 class WriteService implements WriteServiceInterface
@@ -102,7 +102,7 @@ class WriteService implements WriteServiceInterface
         try {
             $this->quoteRepository->save($quote);
         } catch (\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             throw new InputException('Unable to save address. Please, check input data.');
         }
         return $quote->getShippingAddress()->getId();
diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json
index c9f6e783f684d97657ac0be5ae8b3c5c4bac55a5..bfb7b17b422f2715f0250ca6d42cdef1e0dd55d8 100644
--- a/app/code/Magento/Checkout/composer.json
+++ b/app/code/Magento/Checkout/composer.json
@@ -3,28 +3,28 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-authorization": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-gift-message": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-msrp": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-authorization": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-gift-message": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-msrp": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json
index ea79b7e58e0ea1365bfd1bc5c385d4266c94d2dd..8463f4a91f45421e63a54f25db7ebec9a5e38bde 100644
--- a/app/code/Magento/CheckoutAgreements/composer.json
+++ b/app/code/Magento/CheckoutAgreements/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php
index 29019f02ee3e8965787c1a0e1d7a819affd7a476..6b5ac115db2b2c489c78fd7f24316579821651d4 100644
--- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php
+++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php
@@ -47,7 +47,7 @@ class Directive extends \Magento\Backend\App\Action
         } catch (\Exception $e) {
             $image->open($this->_objectManager->get('Magento\Cms\Model\Wysiwyg\Config')->getSkinImagePlaceholderUrl());
             $response->setHeader('Content-Type', $image->getMimeType())->setBody($image->getImage());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php b/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
index d0610198550f7e30095a398abd8b5fd60d83526d..4c97a28717c47aed287dc245611c7c81dbd4d0d1 100644
--- a/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/Resource/Page/Grid/Collection.php
@@ -27,7 +27,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -36,7 +36,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Cms/Ui/DataProvider/Page/Row/Actions.php b/app/code/Magento/Cms/Ui/DataProvider/Page/Row/Actions.php
index 8c10225dd3e7a0da3a7c74c1cbe963bf58690ef7..85ef7f19c4cf56c29e509ee14e03ba2b61139282 100644
--- a/app/code/Magento/Cms/Ui/DataProvider/Page/Row/Actions.php
+++ b/app/code/Magento/Cms/Ui/DataProvider/Page/Row/Actions.php
@@ -16,7 +16,7 @@ class Actions implements RowInterface
     /**
      * Url path
      */
-    const URL_PATH = 'adminhtml/cms_page/edit';
+    const URL_PATH = 'cms/page/edit';
 
     /**
      * @var UrlBuilder
diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json
index 6ab46844c971136b783ed399fe27af098ec938ec..a21c486469f6cd80c0c137ae8ab8ae2a15083757 100644
--- a/app/code/Magento/Cms/composer.json
+++ b/app/code/Magento/Cms/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-email": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-email": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CmsUrlRewrite/composer.json b/app/code/Magento/CmsUrlRewrite/composer.json
index 934d840a0041fb8623c8e2b43138e156ff3ca2b6..32a478b3fba149fd0a29d7b08067890690216e96 100644
--- a/app/code/Magento/CmsUrlRewrite/composer.json
+++ b/app/code/Magento/CmsUrlRewrite/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-url-rewrite": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-url-rewrite": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ConfigurableImportExport/composer.json b/app/code/Magento/ConfigurableImportExport/composer.json
index fac1ee9342dc64d5f5c4f718ef733ba2cf481ce3..de3e60c4f3cab0004c4ae94948fd134bb3e8c0d4 100644
--- a/app/code/Magento/ConfigurableImportExport/composer.json
+++ b/app/code/Magento/ConfigurableImportExport/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-catalog-import-export": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/module-configurable-product": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-catalog-import-export": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/module-configurable-product": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
index 688d04e2f09d1eaf330a52c307c3edc5912ed3a4..961e7861f02aee3b4214fd656b54e5189e5f4615 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php
@@ -163,7 +163,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      * @param \Magento\Core\Helper\File\Storage\Database $fileStorageDb
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param ProductRepositoryInterface $productRepository
      * @param \Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory $typeConfigurableFactory
      * @param \Magento\Eav\Model\EntityFactory $entityFactory
@@ -187,7 +187,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
         \Magento\Core\Helper\File\Storage\Database $fileStorageDb,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         ProductRepositoryInterface $productRepository,
         \Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory $typeConfigurableFactory,
         \Magento\Eav\Model\EntityFactory $entityFactory,
diff --git a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Collection/AssociatedProduct.php b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Collection/AssociatedProduct.php
index 3a6ea1b12da6a5c4b9a0e165ef4c5d3b8d940482..c9c9e020bd5513cb977151e5c8ba20a8b941e9e2 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Collection/AssociatedProduct.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Collection/AssociatedProduct.php
@@ -40,7 +40,7 @@ class AssociatedProduct extends \Magento\Catalog\Model\Resource\Product\Collecti
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -67,7 +67,7 @@ class AssociatedProduct extends \Magento\Catalog\Model\Resource\Product\Collecti
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
index 7ccbfe16b5922f714da46a1bf35ee24903477753..2d8efc12b7a3ebb853607b96413a9d93d5a4b92e 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
+++ b/app/code/Magento/ConfigurableProduct/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
@@ -66,7 +66,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -79,7 +79,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json
index 8b2ef52455183109889a23ead016e0c27c345589..faa5a31fdf94bf2b6fb05352ae3fd5ee37ff6715 100644
--- a/app/code/Magento/ConfigurableProduct/composer.json
+++ b/app/code/Magento/ConfigurableProduct/composer.json
@@ -3,23 +3,23 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-catalog-rule": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-webapi": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-catalog-rule": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-webapi": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json
index 988d8a4014eaad40cd7386835798c740b6574cf5..21e57df75ebc46022203334026547866c3168fe0 100644
--- a/app/code/Magento/Contact/composer.json
+++ b/app/code/Magento/Contact/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Core/Model/File/Storage/Database.php b/app/code/Magento/Core/Model/File/Storage/Database.php
index 61d9202cc4dfe493eb5c6d2a8b5514b6e3661fae..6484ffcb070318e0241d7735a5fd161c20248f75 100644
--- a/app/code/Magento/Core/Model/File/Storage/Database.php
+++ b/app/code/Magento/Core/Model/File/Storage/Database.php
@@ -233,7 +233,7 @@ class Database extends \Magento\Core\Model\File\Storage\Database\AbstractDatabas
                 $this->_getResource()->saveFile($file);
             } catch (\Exception $e) {
                 $this->_errors[] = $e->getMessage();
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Core/Model/File/Storage/Directory/Database.php b/app/code/Magento/Core/Model/File/Storage/Directory/Database.php
index be3f8cbd10abc8ca165dd8a3017cb06bf4c6c632..0174d3b1c9047af6ecfae238223ce261e950d9cc 100644
--- a/app/code/Magento/Core/Model/File/Storage/Directory/Database.php
+++ b/app/code/Magento/Core/Model/File/Storage/Directory/Database.php
@@ -201,7 +201,7 @@ class Database extends \Magento\Core\Model\File\Storage\Database\AbstractDatabas
                     throw new \Magento\Framework\Model\Exception(__('Parent directory does not exist: %1', $dir['path']));
                 }
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Core/Model/File/Storage/File.php b/app/code/Magento/Core/Model/File/Storage/File.php
index cbc14e1f21fcd0a878ed1fa3ccc4e2dd2054370b..66ac32332d00553ed14c19bdfcaac144f328e5a8 100644
--- a/app/code/Magento/Core/Model/File/Storage/File.php
+++ b/app/code/Magento/Core/Model/File/Storage/File.php
@@ -50,18 +50,18 @@ class File
     protected $_errors = [];
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Core\Helper\File\Storage\Database $storageHelper
      * @param \Magento\Core\Helper\File\Media $mediaHelper
      * @param \Magento\Core\Model\Resource\File\Storage\File $fileUtility
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Core\Helper\File\Storage\Database $storageHelper,
         \Magento\Core\Helper\File\Media $mediaHelper,
         \Magento\Core\Model\Resource\File\Storage\File $fileUtility
@@ -193,7 +193,7 @@ class File
             try {
                 $fileInfo = $this->_mediaHelper->collectFileInfo($this->getMediaBaseDirectory(), $fileName);
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 continue;
             }
 
@@ -221,7 +221,7 @@ class File
                 $this->{$callback}($part);
             } catch (\Exception $e) {
                 $this->_errors[] = $e->getMessage();
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
@@ -284,7 +284,7 @@ class File
 
                 return $this->_fileUtility->saveFile($filename, $file['content'], $overwrite);
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 throw new \Magento\Framework\Model\Exception(
                     __('Unable to save file "%1" at "%2"', $file['filename'], $file['directory'])
                 );
diff --git a/app/code/Magento/Core/Model/Layout/Merge.php b/app/code/Magento/Core/Model/Layout/Merge.php
index d12c1a07b963ddd1a7ddaed1e99d570b01ec0ac6..a1533f98efb5b846730f43b032c35c6fcbeab978 100644
--- a/app/code/Magento/Core/Model/Layout/Merge.php
+++ b/app/code/Magento/Core/Model/Layout/Merge.php
@@ -113,7 +113,7 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
     protected $_layoutValidator;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -132,6 +132,27 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
      */
     protected $cacheSuffix;
 
+    /**
+     * Status for new added handle
+     *
+     * @var int
+     */
+    protected $handleAdded = 1;
+
+    /**
+     * Status for handle being processed
+     *
+     * @var int
+     */
+    protected $handleProcessing = 2;
+
+    /**
+     * Status for processed handle
+     *
+     * @var int
+     */
+    protected $handleProcessed = 3;
+
     /**
      * Init merge model
      *
@@ -143,7 +164,7 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Framework\Cache\FrontendInterface $cache
      * @param \Magento\Core\Model\Layout\Update\Validator $validator
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\View\Design\ThemeInterface $theme Non-injectable theme instance
      * @param string $cacheSuffix
@@ -157,7 +178,7 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
         \Magento\Framework\App\State $appState,
         \Magento\Framework\Cache\FrontendInterface $cache,
         \Magento\Core\Model\Layout\Update\Validator $validator,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\View\Design\ThemeInterface $theme = null,
         $cacheSuffix = ''
@@ -217,10 +238,10 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
     {
         if (is_array($handleName)) {
             foreach ($handleName as $name) {
-                $this->_handles[$name] = 1;
+                $this->_handles[$name] = $this->handleAdded;
             }
         } else {
-            $this->_handles[$handleName] = 1;
+            $this->_handles[$handleName] = $this->handleAdded;
         }
         return $this;
     }
@@ -436,8 +457,7 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
                 $messages = $this->_layoutValidator->getMessages();
                 //Add first message to exception
                 $message = reset($messages);
-                $this->_logger->addStreamLog(\Magento\Framework\Logger::LOGGER_SYSTEM);
-                $this->_logger->log('Cache file with merged layout: ' . $cacheId . ': ' . $message, \Zend_Log::ERR);
+                $this->_logger->info('Cache file with merged layout: ' . $cacheId . ': ' . $message);
             }
         }
         return $this;
@@ -477,8 +497,16 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
      */
     protected function _merge($handle)
     {
-        $this->_fetchPackageLayoutUpdates($handle);
-        $this->_fetchDbLayoutUpdates($handle);
+        if (!isset($this->_handles[$handle]) || $this->_handles[$handle] == $this->handleAdded) {
+            $this->_handles[$handle] = $this->handleProcessing;
+            $this->_fetchPackageLayoutUpdates($handle);
+            $this->_fetchDbLayoutUpdates($handle);
+            $this->_handles[$handle] = $this->handleProcessed;
+        } elseif ($this->_handles[$handle] == $this->handleProcessing
+            && $this->_appState->getMode() === \Magento\Framework\App\State::MODE_DEVELOPER
+        ) {
+            $this->_logger->info('Cyclic dependency in merged layout for handle: ' . $handle);
+        }
         return $this;
     }
 
@@ -573,8 +601,6 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
         foreach ($updateXml->children() as $child) {
             if (strtolower($child->getName()) == 'update' && isset($child['handle'])) {
                 $this->_merge((string)$child['handle']);
-                // Adding merged layout handle to the list of applied handles
-                $this->addHandle((string)$child['handle']);
             }
         }
         if (isset($updateXml['layout'])) {
@@ -697,9 +723,8 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
                 $errors[] = "{$error->message} Line: {$error->line}";
             }
 
-            $this->_logger->log(
-                sprintf("Theme layout update file '%s' is not valid.\n%s", $fileName, implode("\n", $errors)),
-                \Zend_Log::ERR
+            $this->_logger->info(
+                sprintf("Theme layout update file '%s' is not valid.\n%s", $fileName, implode("\n", $errors))
             );
         }
     }
diff --git a/app/code/Magento/Core/Model/Observer.php b/app/code/Magento/Core/Model/Observer.php
index d3a9341f9f3784ee058430b9415c8d8de6c804f4..9f67373accaa208c39b9ab67694480837d9985eb 100644
--- a/app/code/Magento/Core/Model/Observer.php
+++ b/app/code/Magento/Core/Model/Observer.php
@@ -44,7 +44,7 @@ class Observer
     protected $_registration;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -55,7 +55,7 @@ class Observer
      * @param \Magento\Framework\App\Config\ReinitableConfigInterface $config
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param Theme\Registration $registration
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Framework\App\Cache\Frontend\Pool $cacheFrontendPool,
@@ -64,7 +64,7 @@ class Observer
         \Magento\Framework\App\Config\ReinitableConfigInterface $config,
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Core\Model\Theme\Registration $registration,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->_cacheFrontendPool = $cacheFrontendPool;
         $this->_currentTheme = $design->getDesignTheme();
@@ -102,7 +102,7 @@ class Observer
         try {
             $this->_registration->register($pathPattern);
         } catch (\Magento\Framework\Model\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return $this;
     }
@@ -133,7 +133,7 @@ class Observer
                     $this->_pageAssets->add($identifier, $asset);
                 }
             } catch (\InvalidArgumentException $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
     }
diff --git a/app/code/Magento/Core/Model/Resource/Design/Collection.php b/app/code/Magento/Core/Model/Resource/Design/Collection.php
index 05c1d98f23ef5ca2e5d53e2bd49e9c8ed9ae351b..4d0f641ead44f21088b74d9ab1b5b9de180875e9 100644
--- a/app/code/Magento/Core/Model/Resource/Design/Collection.php
+++ b/app/code/Magento/Core/Model/Resource/Design/Collection.php
@@ -16,7 +16,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -25,7 +25,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Core/Model/Resource/File/Storage/File.php b/app/code/Magento/Core/Model/Resource/File/Storage/File.php
index c2bb3fadf75677d160cd522767c7a26421e2fb7a..74e1eb3c16bdb6ad7ec0b0c65298a9e97dada236 100644
--- a/app/code/Magento/Core/Model/Resource/File/Storage/File.php
+++ b/app/code/Magento/Core/Model/Resource/File/Storage/File.php
@@ -17,15 +17,15 @@ class File
     protected $_filesystem;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
      * @param \Magento\Framework\Filesystem $filesystem
-     * @param \Magento\Framework\Logger $log
+     * @param \Psr\Log\LoggerInterface $log
      */
-    public function __construct(\Magento\Framework\Filesystem $filesystem, \Magento\Framework\Logger $log)
+    public function __construct(\Magento\Framework\Filesystem $filesystem, \Psr\Log\LoggerInterface $log)
     {
         $this->_logger = $log;
         $this->_filesystem = $filesystem;
@@ -98,7 +98,7 @@ class File
         try {
             $this->_filesystem->getDirectoryWrite(DirectoryList::MEDIA)->create($path);
         } catch (\Exception $e) {
-            $this->_logger->log($e->getMessage());
+            $this->_logger->info($e->getMessage());
             throw new \Magento\Framework\Model\Exception(
                 __('Unable to create directory: %1', DirectoryList::MEDIA . '/' . $path)
             );
@@ -125,7 +125,7 @@ class File
                 return true;
             }
         } catch (\Magento\Framework\Filesystem\FilesystemException $e) {
-            $this->_logger->log($e->getMessage());
+            $this->_logger->info($e->getMessage());
             throw new \Magento\Framework\Model\Exception(__('Unable to save file: %1', $filePath));
         }
 
diff --git a/app/code/Magento/Core/Model/Resource/Layout/Link/Collection.php b/app/code/Magento/Core/Model/Resource/Layout/Link/Collection.php
index 0669794c3c750c752f540622369e1ebc24d41445..926b672c14abab341199293b2b778439d978ddc9 100644
--- a/app/code/Magento/Core/Model/Resource/Layout/Link/Collection.php
+++ b/app/code/Magento/Core/Model/Resource/Layout/Link/Collection.php
@@ -15,7 +15,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
     protected $dateTime;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -25,7 +25,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Core/Model/Resource/Layout/Update/Collection.php b/app/code/Magento/Core/Model/Resource/Layout/Update/Collection.php
index 01a14102107d7d3ce020063569d60fe86489f0f9..3254d1aa0022bcf53d5bfc6b1e27daa704e85947 100644
--- a/app/code/Magento/Core/Model/Resource/Layout/Update/Collection.php
+++ b/app/code/Magento/Core/Model/Resource/Layout/Update/Collection.php
@@ -30,7 +30,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -39,7 +39,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Core/composer.json b/app/code/Magento/Core/composer.json
index 4f30dd91346619a04a787e022985378f1165633c..d0f462f935cfe676584cc83def0ee7e1e6d9377e 100644
--- a/app/code/Magento/Core/composer.json
+++ b/app/code/Magento/Core/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-cron": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-cron": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Core/etc/config.xml b/app/code/Magento/Core/etc/config.xml
index 77708c9752012092694185487a8ba1b718beafd8..dda5079bb16a5f58d9c45fc4038d5f61808da2f6 100644
--- a/app/code/Magento/Core/etc/config.xml
+++ b/app/code/Magento/Core/etc/config.xml
@@ -19,11 +19,6 @@
             <debug>
                 <profiler>0</profiler>
             </debug>
-            <log>
-                <active>0</active>
-                <file>system.log</file>
-                <exception_file>exception.log</exception_file>
-            </log>
             <js>
                 <merge_files>0</merge_files>
                 <minify_files>0</minify_files>
diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json
index 99f4759d0ab3cd475899207e95436ea936716d2b..26a0c49e2bcb16bbe86dd9a019a3f0e3d8112611 100644
--- a/app/code/Magento/Cron/composer.json
+++ b/app/code/Magento/Cron/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json
index b3cf1637ddd0c9a81e7d9aadc2d11d059187ce7c..e81038fe6a9bb29117f1b75a1675ba2268c78d37 100644
--- a/app/code/Magento/CurrencySymbol/composer.json
+++ b/app/code/Magento/CurrencySymbol/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
index 5701c366a1d5005e2833030ae9f0e45e3d7806fa..1e2366b20fb8e04714473c5c9bd6c562f326b545 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfo.php
@@ -128,7 +128,7 @@ class PersonalInfo extends \Magento\Backend\Block\Template
             );
             return $this->formatDate($date, TimezoneInterface::FORMAT_TYPE_MEDIUM, true);
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return '';
         }
     }
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php
index fbc41f25069e2176f94a58dc3af7dac0e7bef746..6c67a1f555ef1785e722f1c6db058656e4837707 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php
@@ -115,7 +115,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic
                 'title' => __('Tax Class'),
                 'class' => 'required-entry',
                 'required' => true,
-                'values' => $this->_taxCustomer->toOptionArray(true),
+                'values' => $this->_taxCustomer->toOptionArray(),
             ]
         );
 
diff --git a/app/code/Magento/Customer/Controller/Account/LoginPost.php b/app/code/Magento/Customer/Controller/Account/LoginPost.php
index 412ed7c140d5de6aefb7b4f6f248f63950bf86e1..e409febe60fdb3563d5d65b8192d0b0451de57fd 100644
--- a/app/code/Magento/Customer/Controller/Account/LoginPost.php
+++ b/app/code/Magento/Customer/Controller/Account/LoginPost.php
@@ -159,7 +159,7 @@ class LoginPost extends \Magento\Customer\Controller\Account
                     $this->_getSession()->setUsername($login['username']);
                 } catch (\Exception $e) {
                     // PA DSS violation: this exception log can disclose customer password
-                    // $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                    // $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                     $this->messageManager->addError(__('There was an error validating the login and password.'));
                 }
             } else {
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php
index c1b141f2710bc140e9820f7fa89d0c71d73dbcc0..c0b15e0b4367529daeba48534487094b3d806de2 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Wishlist.php
@@ -23,7 +23,7 @@ class Wishlist extends \Magento\Customer\Controller\Adminhtml\Index
             try {
                 $this->_objectManager->create('Magento\Wishlist\Model\Item')->load($itemId)->delete();
             } catch (\Exception $exception) {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($exception);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($exception);
             }
         }
 
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index 5d4dec963603d7fbb5cf948e576b5c9c31047e50..4117585521568920fae4d5502435d19d8c1b9949 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -25,7 +25,7 @@ use Magento\Framework\Exception\NoSuchEntityException;
 use Magento\Framework\Exception\State\ExpiredException;
 use Magento\Framework\Exception\State\InputMismatchException;
 use Magento\Framework\Exception\State\InvalidTransitionException;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Mail\Exception as MailException;
 use Magento\Framework\Mail\Template\TransportBuilder;
 use Magento\Framework\Math\Random;
@@ -311,7 +311,7 @@ class AccountManagement implements AccountManagementInterface
             );
         } catch (MailException $e) {
             // If we are not able to send a new account email, this should be ignored
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
     }
 
@@ -431,7 +431,7 @@ class AccountManagement implements AccountManagementInterface
             }
         } catch (MailException $e) {
             // If we are not able to send a reset password email, this should be ignored
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
     }
 
@@ -584,7 +584,7 @@ class AccountManagement implements AccountManagementInterface
             }
         } catch (MailException $e) {
             // If we are not able to send a new account email, this should be ignored
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
     }
 
@@ -638,7 +638,7 @@ class AccountManagement implements AccountManagementInterface
         try {
             $this->sendPasswordResetNotificationEmail($customer);
         } catch (MailException $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
 
         return true;
diff --git a/app/code/Magento/Customer/Model/Attribute/Data/Postcode.php b/app/code/Magento/Customer/Model/Attribute/Data/Postcode.php
index f492c92be48d7f6dc6e149846e1dd3d3ab2cb458..489c138cef5ad3237a29412519e8f8ddb710f3ce 100644
--- a/app/code/Magento/Customer/Model/Attribute/Data/Postcode.php
+++ b/app/code/Magento/Customer/Model/Attribute/Data/Postcode.php
@@ -8,7 +8,7 @@ use Magento\Directory\Helper\Data as DirectoryHelper;
 use Magento\Eav\Model\AttributeDataFactory;
 use Magento\Framework\App\RequestInterface;
 use Magento\Framework\Locale\ResolverInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Stdlib\DateTime\TimezoneInterface as MagentoTimezone;
 
 /**
diff --git a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Website.php b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Website.php
index d22315515a4bfe905027b0bb94bdd87b3aad44d3..22c524c3ff73bed9da6cb50dc87d00e1d5682c68 100644
--- a/app/code/Magento/Customer/Model/Customer/Attribute/Source/Website.php
+++ b/app/code/Magento/Customer/Model/Customer/Attribute/Source/Website.php
@@ -38,7 +38,7 @@ class Website extends \Magento\Eav\Model\Entity\Attribute\Source\Table
     public function getAllOptions()
     {
         if (!$this->_options) {
-            $this->_options = $this->_store->getWebsiteValuesForForm(true, true);
+            $this->_options = $this->_store->getWebsiteValuesForForm(false, true);
         }
 
         return $this->_options;
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php b/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php
index b7f66440bf4dfeed400c4ac9e9f5aad2488a7e42..e5c0978f140307a35b71e6b4f4e0e0fccccf2d8f 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php
@@ -57,7 +57,7 @@ abstract class AbstractData
     protected $_localeResolver;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -78,7 +78,7 @@ abstract class AbstractData
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param string|int|bool $value
@@ -87,7 +87,7 @@ abstract class AbstractData
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         $value,
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/File.php b/app/code/Magento/Customer/Model/Metadata/Form/File.php
index 926e2078f27465b37b7a37c2e43eaa3a25fe0001..2d8f7a9b78f9e4fc81d39738ae85ab47e595a594 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/File.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/File.php
@@ -44,7 +44,7 @@ class File extends AbstractData
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param null $value
@@ -57,7 +57,7 @@ class File extends AbstractData
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         $value,
@@ -270,7 +270,7 @@ class File extends AbstractData
                 $uploader->save($mediaDir->getAbsolutePath($this->_entityTypeCode), $value['name']);
                 $result = $uploader->getUploadedFileName();
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php b/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php
index 8cd0d39d0ead8fb27cbc3ab4bf54a36bc2368d47..531f59819281ba8a9349411fbc7b475890df18ab 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/Postcode.php
@@ -8,7 +8,7 @@ use Magento\Customer\Api\Data\AttributeMetadataInterface;
 use Magento\Customer\Model\Metadata\ElementFactory;
 use Magento\Directory\Helper\Data as DirectoryHelper;
 use Magento\Framework\Locale\ResolverInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Stdlib\DateTime\TimezoneInterface as MagentoTimezone;
 
 /**
diff --git a/app/code/Magento/Customer/Model/Metadata/Form/Text.php b/app/code/Magento/Customer/Model/Metadata/Form/Text.php
index b9aa53407860c3ac9214b9417ff384c9fc895ab4..34802ae362c811c082e6d0a6e6573fa17aef5394 100644
--- a/app/code/Magento/Customer/Model/Metadata/Form/Text.php
+++ b/app/code/Magento/Customer/Model/Metadata/Form/Text.php
@@ -17,7 +17,7 @@ class Text extends AbstractData
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param string $value
@@ -27,7 +27,7 @@ class Text extends AbstractData
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         $value,
diff --git a/app/code/Magento/Customer/Model/Resource/Customer/Collection.php b/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
index ab1f24796f95b3e068831d52c80daeee36400dbf..dfd228083a10e04d430c51ae422a314e295e432f 100644
--- a/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
+++ b/app/code/Magento/Customer/Model/Resource/Customer/Collection.php
@@ -28,7 +28,7 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -44,7 +44,7 @@ class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Customer/Model/Vat.php b/app/code/Magento/Customer/Model/Vat.php
index 0bd3d70b8d2c70c6f5ec093e5d01937680fe697f..de7be3cc6061cfec44c2192d8b722fff9cfcaed5 100644
--- a/app/code/Magento/Customer/Model/Vat.php
+++ b/app/code/Magento/Customer/Model/Vat.php
@@ -5,7 +5,7 @@
 namespace Magento\Customer\Model;
 
 use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Store\Model\ScopeInterface;
 
 /**
@@ -172,7 +172,7 @@ class Vat
         );
 
         if (!extension_loaded('soap')) {
-            $this->logger->logException(new \Magento\Framework\Model\Exception(__('PHP SOAP extension is required.')));
+            $this->logger->critical(new \Magento\Framework\Model\Exception(__('PHP SOAP extension is required.')));
             return $gatewayResponse;
         }
 
diff --git a/app/code/Magento/Customer/Model/Visitor.php b/app/code/Magento/Customer/Model/Visitor.php
index 0a41a5ba682cf9554e4330eb56a66a90947574c3..642e33c184c5ba1b3477987d45187b518302b176 100644
--- a/app/code/Magento/Customer/Model/Visitor.php
+++ b/app/code/Magento/Customer/Model/Visitor.php
@@ -164,7 +164,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel
             $this->_eventManager->dispatch('visitor_activity_save', ['visitor' => $this]);
             $this->session->setVisitorData($this->getData());
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return $this;
     }
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index 48282323309a2d093489c85212ccc8f6ddf85aac..b43bee3bd5227c72e527a5e1eee608ce25e6e695 100644
--- a/app/code/Magento/Customer/composer.json
+++ b/app/code/Magento/Customer/composer.json
@@ -3,28 +3,28 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-newsletter": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-review": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-authorization": "0.42.0-beta1",
-        "magento/module-integration": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-newsletter": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-review": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-authorization": "0.42.0-beta2",
+        "magento/module-integration": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml
index 10a4fcbd2f67215baea83c148bce75131cd61da5..521a80d8c306c793a7a1a56d028a4710548261cb 100644
--- a/app/code/Magento/Customer/etc/config.xml
+++ b/app/code/Magento/Customer/etc/config.xml
@@ -58,7 +58,7 @@ T: {{var telephone}}
 {{depend fax}}F: {{var fax}}{{/depend}}
 {{depend vat_id}}VAT: {{var vat_id}}{{/depend}}</text>
                 <oneline>{{depend prefix}}{{var prefix}} {{/depend}}{{var firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var lastname}}{{depend suffix}} {{var suffix}}{{/depend}}, {{var street}}, {{var city}}, {{var region}} {{var postcode}}, {{var country}}</oneline>
-                <html><![CDATA[{{depend prefix}}{{var prefix}} {{/depend}}{{var firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var lastname}}{{depend suffix}} {{var suffix}}{{/depend}}<br/>
+                <html><![CDATA[{{depend prefix}}{{var prefix}} {{/depend}}{{var firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var lastname}}{{depend suffix}} {{var suffix}}{{/depend}}{{depend firstname}}<br/>{{/depend}}
 {{depend company}}{{var company}}<br />{{/depend}}
 {{if street1}}{{var street1}}<br />{{/if}}
 {{depend street2}}{{var street2}}<br />{{/depend}}
diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json
index d87b7f176a3ce94f9fc1e886cfacdb322971a972..eb6cfecd3b82b473073f1e9be77f54afded415bf 100644
--- a/app/code/Magento/CustomerImportExport/composer.json
+++ b/app/code/Magento/CustomerImportExport/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor.php
index 795726faba28c9ab9a787c0eaf257afeb2a19917..c412dc0c274d188b3f53e2065ba89b58843a9fba 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor.php
@@ -123,7 +123,7 @@ class Editor extends \Magento\Backend\App\Action
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t load the list of themes.'));
             $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/AssignThemeToStore.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/AssignThemeToStore.php
index 763971b0af06fc4f9ce13adf49d3af3b10cfb8c9..f5083bc5691f095cc2560ddf7dc4eda0cca8a1e9 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/AssignThemeToStore.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/AssignThemeToStore.php
@@ -77,7 +77,7 @@ class AssignThemeToStore extends \Magento\DesignEditor\Controller\Adminhtml\Syst
             }
             $response = ['message' => $successMessage, 'themeId' => $themeCustomization->getId()];
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response = ['error' => true, 'message' => __('This theme is not assigned.')];
         }
         $this->getResponse()->representJson($coreHelper->jsonEncode($response));
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Duplicate.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Duplicate.php
index 2cb0ede931f9c08359c4996f68df80596eff1ab7..eca41fcefbff3aabce0f81c654e0e85922e1d190 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Duplicate.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Duplicate.php
@@ -35,9 +35,9 @@ class Duplicate extends \Magento\DesignEditor\Controller\Adminhtml\System\Design
             $this->messageManager->addSuccess(__('You saved a duplicate copy of this theme in "My Customizations."'));
         } catch (CoreException $e) {
             $this->messageManager->addError($e->getMessage());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__('You cannot duplicate this theme.'));
         }
         $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Files/TreeJson.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Files/TreeJson.php
index e8955aa585b22512f995f2e9d0c0429fd610571f..a6623aded0a756e80dc39378f4eef1fc78fb3e67 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Files/TreeJson.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Files/TreeJson.php
@@ -23,7 +23,7 @@ class TreeJson extends \Magento\Theme\Controller\Adminhtml\System\Design\Wysiwyg
                 )
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->getResponse()->representJson(
                 $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode([])
             );
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php
index 14e1134e7a77e1979c40ad20f82bda874d67dd10..2de06eed51ea4366455e0a8c39c3954e37157e88 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php
@@ -154,12 +154,12 @@ class Launch extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed
             $this->_view->renderLayout();
         } catch (CoreException $e) {
             $this->messageManager->addException($e, $e->getMessage());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('adminhtml/*/');
             return;
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('Sorry, there was an unknown error.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('adminhtml/*/');
             return;
         }
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/LoadThemeList.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/LoadThemeList.php
index 6c4695c701be24d64b569a051158fabad08b7466..a33bd2d476d7e3e17166cc0e7f31279e65993239 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/LoadThemeList.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/LoadThemeList.php
@@ -41,7 +41,7 @@ class LoadThemeList extends \Magento\DesignEditor\Controller\Adminhtml\System\De
 
             $response = ['content' => $this->_view->getLayout()->getOutput()];
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response = ['error' => __('Sorry, but we can\'t load the theme list.')];
         }
         $this->getResponse()->representJson($coreHelper->jsonEncode($response));
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/QuickEdit.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/QuickEdit.php
index f690b4b7cfc21d6126e3ca7de7cdbebda43162bf..191ba153fba26a4c49098dd274272888a90318b8 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/QuickEdit.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/QuickEdit.php
@@ -31,9 +31,9 @@ class QuickEdit extends \Magento\DesignEditor\Controller\Adminhtml\System\Design
             $response = ['success' => true];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response = ['error' => true, 'message' => __('This theme is not saved.')];
         }
         $this->getResponse()->representJson($coreHelper->jsonEncode($response));
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Revert.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Revert.php
index 108d9298fbb26ef374b50c8f7e2d5d62904473ba..7440420675a7573d99f8bf824760c8537bd1749c 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Revert.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Revert.php
@@ -47,7 +47,7 @@ class Revert extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed
             }
             $response = ['message' => $message];
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response = ['error' => true, 'message' => __('Unknown error')];
         }
         /** @var $coreHelper \Magento\Core\Helper\Data */
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php
index 899c59803f8fe2210613e1b8008b30aa93f83286..6594a57ebe54919cf889540db5ce704747b02341 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php
@@ -28,7 +28,7 @@ class Save extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Edit
             }
             $response = ['message' => $message];
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response = ['error' => true, 'message' => __('Sorry, there was an unknown error.')];
         }
 
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/DeleteCustomFiles.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/DeleteCustomFiles.php
index 9d3e391833605fdd57acebb10a5dae898c0e0d32..fec2fb908a960fec8d46cdf153c4e6dd7932ff83 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/DeleteCustomFiles.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/DeleteCustomFiles.php
@@ -22,7 +22,7 @@ class DeleteCustomFiles extends \Magento\DesignEditor\Controller\Adminhtml\Syste
             $this->_forward('jsList');
         } catch (\Exception $e) {
             $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/JsList.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/JsList.php
index f815039bb3a4c5ba8cd368a87854ed8cd3a6936b..b260d9e175d545df4ca9e2e3f45578854b16535e 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/JsList.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/JsList.php
@@ -24,7 +24,7 @@ class JsList extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed
                 $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveQuickStyleImage.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveQuickStyleImage.php
index 933c7c7546bcbe783dd316818ba655bdf47f5486..12b8a161c678cfcda9247bd38c283071c035cfd1 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveQuickStyleImage.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveQuickStyleImage.php
@@ -41,14 +41,14 @@ class RemoveQuickStyleImage extends \Magento\DesignEditor\Controller\Adminhtml\S
             $response = ['error' => false, 'content' => $result];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $errorMessage = __(
                 'Something went wrong uploading the image.' .
                 ' Please check the file format and try again (JPEG, GIF, or PNG).'
             );
             $response = ['error' => true, 'message' => $errorMessage];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveStoreLogo.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveStoreLogo.php
index a28c14fcc0a806c3a82038e6153e46725810ab32..1d2e9666f080cfe41951f15fee27610408c5ac6e 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveStoreLogo.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/RemoveStoreLogo.php
@@ -50,14 +50,14 @@ class RemoveStoreLogo extends \Magento\DesignEditor\Controller\Adminhtml\System\
             $response = ['error' => false, 'content' => []];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $errorMessage = __(
                 'Something went wrong uploading the image.' .
                 ' Please check the file format and try again (JPEG, GIF, or PNG).'
             );
             $response = ['error' => true, 'message' => $errorMessage];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php
index 692a1479a96086b79d17b64c4f12254a1a754fb4..f7fb123df044622ed48dffe86bf8253ca69e70a3 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php
@@ -27,10 +27,10 @@ class ReorderJs extends \Magento\DesignEditor\Controller\Adminhtml\System\Design
             $result = ['success' => true];
         } catch (CoreException $e) {
             $result = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $result = ['error' => true, 'message' => __('We cannot upload the CSS file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveCssContent.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveCssContent.php
index 6edc4c2dc49c012def426e8f9b7a20d18c971405..8e2d1de1c79a2aae482f585c9edfc8c0cc14d1e1 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveCssContent.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveCssContent.php
@@ -35,10 +35,10 @@ class SaveCssContent extends \Magento\DesignEditor\Controller\Adminhtml\System\D
             ];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $response = ['error' => true, 'message' => __('We can\'t save the custom css file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveImageSizing.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveImageSizing.php
index c9d65e7636cf7e8b840828e0d7bca08320a03ca5..d29d45cdedc6f968b47c6955713408c8190f08b3 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveImageSizing.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveImageSizing.php
@@ -35,10 +35,10 @@ class SaveImageSizing extends \Magento\DesignEditor\Controller\Adminhtml\System\
             $result = ['success' => true, 'message' => __('We saved the image sizes.')];
         } catch (CoreException $e) {
             $result = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $result = ['error' => true, 'message' => __('We can\'t save image sizes.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveQuickStyles.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveQuickStyles.php
index d14b8bd6365d4774718d3dd2d9464c12962fe005..53b8cbb302685ce34a025683343e95ce6f9a7fd6 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveQuickStyles.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/SaveQuickStyles.php
@@ -31,14 +31,14 @@ class SaveQuickStyles extends \Magento\DesignEditor\Controller\Adminhtml\System\
             $response = ['success' => true];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $errorMessage = __(
                 'Something went wrong uploading the image.' .
                 ' Please check the file format and try again (JPEG, GIF, or PNG).'
             );
             $response = ['error' => true, 'message' => $errorMessage];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php
index 928962e41e0f63ab291730be3141d4c6160d7f55..b6bce92f5701576fb7fef661e3ee59f3798dcc8f 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php
@@ -39,10 +39,10 @@ class Upload extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed
             ];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $response = ['error' => true, 'message' => __('We cannot upload the CSS file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php
index 62e7e0922a9225d2dd4abe345430671052f9991a..53120e8379b449f5cb6ab084673d89a425440268 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php
@@ -33,10 +33,10 @@ class UploadJs extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\
             return;
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $response = ['error' => true, 'message' => __('We cannot upload the JS file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadQuickStyleImage.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadQuickStyleImage.php
index 113765a967d591117da1ed371fc488c4a80e2c84..9ffd1d2e8cb3cbe42a0b9c6b8cd291a775d9c92b 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadQuickStyleImage.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadQuickStyleImage.php
@@ -39,14 +39,14 @@ class UploadQuickStyleImage extends \Magento\DesignEditor\Controller\Adminhtml\S
         } catch (CoreException $e) {
             $this->messageManager->addError($e->getMessage());
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $errorMessage = __(
                 'Something went wrong uploading the image.' .
                 ' Please check the file format and try again (JPEG, GIF, or PNG).'
             );
             $response = ['error' => true, 'message' => $errorMessage];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadStoreLogo.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadStoreLogo.php
index fa16fc80f141f5fca40e0b83f736edd82a6fc516..ee93ce4c57b1d19771b11d284a651037e82a8ffc 100644
--- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadStoreLogo.php
+++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadStoreLogo.php
@@ -44,14 +44,14 @@ class UploadStoreLogo extends \Magento\DesignEditor\Controller\Adminhtml\System\
             $response = ['error' => false, 'content' => ['name' => basename($storeLogo->getValue())]];
         } catch (CoreException $e) {
             $response = ['error' => true, 'message' => $e->getMessage()];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         } catch (\Exception $e) {
             $errorMessage = __(
                 'Something went wrong uploading the image.' .
                 ' Please check the file format and try again (JPEG, GIF, or PNG).'
             );
             $response = ['error' => true, 'message' => $errorMessage];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($response)
diff --git a/app/code/Magento/DesignEditor/composer.json b/app/code/Magento/DesignEditor/composer.json
index f5ae9e6fba7ed3cafe30d580208e1c593884e689..badd482f1f9a7cd28d8c15d88ac3319b3ebaad87 100644
--- a/app/code/Magento/DesignEditor/composer.json
+++ b/app/code/Magento/DesignEditor/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php
index e5dd061c91d47f2744c7d6b01c29679bcb99f34f..b81ffca5c1081fc5cdbb8aedb08ee614b6b313ac 100644
--- a/app/code/Magento/Dhl/Model/Carrier.php
+++ b/app/code/Magento/Dhl/Model/Carrier.php
@@ -184,7 +184,7 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
@@ -210,7 +210,7 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
         \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
@@ -245,7 +245,7 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
         parent::__construct(
             $scopeConfig,
             $rateErrorFactory,
-            $logAdapterFactory,
+            $logger,
             $xmlElFactory,
             $rateFactory,
             $rateMethodFactory,
diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json
index 81853cf04407c64c4326a8fdeeee3f0fa8bb1319..6a5e7b77d1333748878718ae6ab3a20d67099ed4 100644
--- a/app/code/Magento/Dhl/composer.json
+++ b/app/code/Magento/Dhl/composer.json
@@ -3,21 +3,21 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Directory/Model/PriceCurrency.php b/app/code/Magento/Directory/Model/PriceCurrency.php
index 1768f841a494ebf8cc392912c038ce00545c4220..3cc16e54ca6e21c768d3f124936ee3098d180162 100644
--- a/app/code/Magento/Directory/Model/PriceCurrency.php
+++ b/app/code/Magento/Directory/Model/PriceCurrency.php
@@ -6,7 +6,7 @@ namespace Magento\Directory\Model;
 
 use Magento\Framework\App\ScopeInterface;
 use Magento\Store\Model\StoreManagerInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Store\Model\Store;
 
 /**
@@ -135,7 +135,7 @@ class PriceCurrency implements \Magento\Framework\Pricing\PriceCurrencyInterface
                 $scope = $this->storeManager->getStore($scope);
             }
         } catch (\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             $scope = $this->storeManager->getStore();
         }
 
diff --git a/app/code/Magento/Directory/Model/Resource/Country/Collection.php b/app/code/Magento/Directory/Model/Resource/Country/Collection.php
index dbf8bbd6c5917981442fbe1f7a439b30edef649e..ed505ab7aa0f4f69f512080859947e1d06e49ba0 100644
--- a/app/code/Magento/Directory/Model/Resource/Country/Collection.php
+++ b/app/code/Magento/Directory/Model/Resource/Country/Collection.php
@@ -43,7 +43,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Locale\ListsInterface $localeLists
@@ -56,7 +56,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Locale\ListsInterface $localeLists,
diff --git a/app/code/Magento/Directory/Model/Resource/Region/Collection.php b/app/code/Magento/Directory/Model/Resource/Region/Collection.php
index 3669796392ec85d2b31692f07b6a9eace72e76e8..25e32fd40f55046c742ba0334f1bba0a134057f1 100644
--- a/app/code/Magento/Directory/Model/Resource/Region/Collection.php
+++ b/app/code/Magento/Directory/Model/Resource/Region/Collection.php
@@ -31,7 +31,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
@@ -40,7 +40,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json
index 551abbb12174e3f4b4830b4f24f7eea2290f2c32..ffabf1f65c02d4ff081875c16502d76283d19f0f 100644
--- a/app/code/Magento/Directory/composer.json
+++ b/app/code/Magento/Directory/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Downloadable/Model/Product/Type.php b/app/code/Magento/Downloadable/Model/Product/Type.php
index 054db0e1eb825165c63c86d0127a3020419444aa..3fa35f6189e4a7bd68c7091954cfd62deb8b3893 100644
--- a/app/code/Magento/Downloadable/Model/Product/Type.php
+++ b/app/code/Magento/Downloadable/Model/Product/Type.php
@@ -63,7 +63,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\Virtual
      * @param \Magento\Core\Helper\File\Storage\Database $fileStorageDb
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param ProductRepositoryInterface $productRepository
      * @param \Magento\Downloadable\Helper\File $downloadableFile
      * @param \Magento\Downloadable\Model\Resource\SampleFactory $sampleResFactory
@@ -82,7 +82,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\Virtual
         \Magento\Core\Helper\File\Storage\Database $fileStorageDb,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         ProductRepositoryInterface $productRepository,
         \Magento\Downloadable\Helper\File $downloadableFile,
         \Magento\Downloadable\Model\Resource\SampleFactory $sampleResFactory,
diff --git a/app/code/Magento/Downloadable/composer.json b/app/code/Magento/Downloadable/composer.json
index ad7fd26302ceaca88ed80497a27ba81b2e3ce2b3..099aada6176828bc9aac15f17f6f13754f4fb4a0 100644
--- a/app/code/Magento/Downloadable/composer.json
+++ b/app/code/Magento/Downloadable/composer.json
@@ -3,26 +3,26 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-gift-message": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-msrp": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-gift-message": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-msrp": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php b/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php
index d27bd6c57814042e4855fe5c519499a522c10974..f8a52ed7bde3d415e13ba2070b323f79c938789b 100644
--- a/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php
+++ b/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php
@@ -75,18 +75,18 @@ abstract class AbstractData
     protected $_localeResolver;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Locale\ResolverInterface $localeResolver
     ) {
         $this->_localeDate = $localeDate;
diff --git a/app/code/Magento/Eav/Model/Attribute/Data/File.php b/app/code/Magento/Eav/Model/Attribute/Data/File.php
index 8ef938a8abf6c20abc0be26bdc9f6332dd909f36..94b0e6ff1c674ea60029b541223b0d950d9af585 100644
--- a/app/code/Magento/Eav/Model/Attribute/Data/File.php
+++ b/app/code/Magento/Eav/Model/Attribute/Data/File.php
@@ -38,7 +38,7 @@ class File extends \Magento\Eav\Model\Attribute\Data\AbstractData
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param \Magento\Framework\Url\EncoderInterface $urlEncoder
      * @param \Magento\Core\Model\File\Validator\NotProtectedExtension $fileValidator
@@ -46,7 +46,7 @@ class File extends \Magento\Eav\Model\Attribute\Data\AbstractData
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         \Magento\Framework\Url\EncoderInterface $urlEncoder,
         \Magento\Core\Model\File\Validator\NotProtectedExtension $fileValidator,
@@ -244,7 +244,7 @@ class File extends \Magento\Eav\Model\Attribute\Data\AbstractData
                 $fileName = $uploader->getUploadedFileName();
                 $this->getEntity()->setData($attribute->getAttributeCode(), $fileName);
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Eav/Model/Attribute/Data/Text.php b/app/code/Magento/Eav/Model/Attribute/Data/Text.php
index 32e1485353669eaa6e05d09c17f32546ca15b0c2..e32506f45dd1fcc778016473b9942de3a2e5c29b 100644
--- a/app/code/Magento/Eav/Model/Attribute/Data/Text.php
+++ b/app/code/Magento/Eav/Model/Attribute/Data/Text.php
@@ -20,13 +20,13 @@ class Text extends \Magento\Eav\Model\Attribute\Data\AbstractData
 
     /**
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
      * @param \Magento\Framework\Stdlib\String $stringHelper
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
         \Magento\Framework\Stdlib\String $stringHelper
     ) {
diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
index 4d4709d1ef6a93af472bf973ce74ea2bfdb3b9fb..9c10fc846bce234dfd1992822875ad33fbc30239 100644
--- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
+++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php
@@ -115,7 +115,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -127,7 +127,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Eav/Model/Entity/Setup/Context.php b/app/code/Magento/Eav/Model/Entity/Setup/Context.php
index 2ce7e2f7411cb2d36d7c1574c1141036046173ca..b08b99d84ab25ba121887f8de16d240ff98ad007 100644
--- a/app/code/Magento/Eav/Model/Entity/Setup/Context.php
+++ b/app/code/Magento/Eav/Model/Entity/Setup/Context.php
@@ -14,7 +14,7 @@ class Context extends \Magento\Framework\Module\Setup\Context
     protected $attributeMapper;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\App\Resource $appResource
      * @param \Magento\Framework\Module\Dir\Reader $modulesReader
@@ -26,7 +26,7 @@ class Context extends \Magento\Framework\Module\Setup\Context
      * @param PropertyMapperInterface $attributeMapper
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\App\Resource $appResource,
         \Magento\Framework\Module\Dir\Reader $modulesReader,
diff --git a/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php b/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php
index 0a9317b4f9f083245c3570e7d1e789af173b3a73..6cb28f94a1cc2ea38309aa6049d560161aea66e0 100644
--- a/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php
@@ -39,7 +39,7 @@ abstract class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\C
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -49,7 +49,7 @@ abstract class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\C
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Collection.php b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Collection.php
index 8a98da583ab4d6555481cd6d0daa48cdd5033bdd..240a6419a323076b7e5f9b8247adf0439189bacd 100644
--- a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Collection.php
@@ -27,7 +27,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -36,7 +36,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Grid/Collection.php b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Grid/Collection.php
index a6ac2254c5e230400654d59c7e175cca9b01b24d..5aa44c5e8235e0a8592129f2664b300c06c2cc77 100644
--- a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Grid/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Grid/Collection.php
@@ -20,7 +20,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collec
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
@@ -29,7 +29,7 @@ class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collec
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Registry $registryManager,
diff --git a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Option/Collection.php b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Option/Collection.php
index 103f98ab770781d4a5a2438587844d29a96f4009..63f6ace2580efd3b95ca4aa27d1d41434fadbca3 100644
--- a/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Option/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Entity/Attribute/Option/Collection.php
@@ -30,7 +30,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\App\Resource $coreResource
@@ -40,7 +40,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\App\Resource $coreResource,
diff --git a/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php b/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php
index 780c1e81c7b2ba0e1190603601a77aa23c76bb69..269fd414eccfec3eb389f5ff0329ecca68a7c889 100644
--- a/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php
@@ -51,7 +51,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -61,7 +61,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Eav/Model/Resource/Form/Fieldset/Collection.php b/app/code/Magento/Eav/Model/Resource/Form/Fieldset/Collection.php
index 5cd3436044bbe3670e571e3f2b61891a3674b7bb..33a959f9b95c8861e49732fb0705a54172ae9a0f 100644
--- a/app/code/Magento/Eav/Model/Resource/Form/Fieldset/Collection.php
+++ b/app/code/Magento/Eav/Model/Resource/Form/Fieldset/Collection.php
@@ -16,7 +16,7 @@ use Magento\Eav\Model\Form\Type;
 use Magento\Framework\Event\ManagerInterface;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 use Magento\Framework\Model\Resource\Db\AbstractDb;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Store\Model\StoreManagerInterface;
 
 class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection
diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json
index 61dd1d12013d7bcc4bbea9c6a99786888a289c53..401bb5a2f2a4fddd63dcec12950527c7796be54f 100644
--- a/app/code/Magento/Eav/composer.json
+++ b/app/code/Magento/Eav/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/DefaultTemplate.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/DefaultTemplate.php
index cc8e45631d35714be7463e4ad24220c906b6b0b5..8ffde1bd2a1644efffa4be0f3f1c7f56d5f01a11 100644
--- a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/DefaultTemplate.php
+++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/DefaultTemplate.php
@@ -29,7 +29,7 @@ class DefaultTemplate extends \Magento\Email\Controller\Adminhtml\Email\Template
                 $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($template->getData())
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php
index 3c0b93101cca54768a55c3ac3e7a8a269f6b8007..1e2c4d369644a6cd4bc5992fc05021cebe67b263 100644
--- a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php
+++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php
@@ -38,7 +38,7 @@ class Delete extends \Magento\Email\Controller\Adminhtml\Email\Template
                 $this->messageManager->addError(
                     __('An error occurred while deleting email template data. Please review log and try again.')
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 // save data in session
                 $this->_objectManager->get(
                     'Magento\Backend\Model\Session'
diff --git a/app/code/Magento/Email/Model/Resource/Template.php b/app/code/Magento/Email/Model/Resource/Template.php
index f4cf0242b54678206f9bd6a9510904c98eac9f7d..6c6fe926b97ccc6776337b47bb745b1bd14ae352 100644
--- a/app/code/Magento/Email/Model/Resource/Template.php
+++ b/app/code/Magento/Email/Model/Resource/Template.php
@@ -99,7 +99,7 @@ class Template extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected function _beforeSave(AbstractModel $object)
     {
         if ($object->isObjectNew()) {
-            $object->setCreatedAt($this->dateTime->formatDate(true));
+            $object->setAddedAt($this->dateTime->formatDate(true));
         }
         $object->setModifiedAt($this->dateTime->formatDate(true));
         $object->setTemplateType((int)$object->getTemplateType());
diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php
index 062afab9e21218a2ad0d44fb22b38b5153039352..5bdfa48d884481a11c545a9babe2f22fe511ad2f 100644
--- a/app/code/Magento/Email/Model/Template/Filter.php
+++ b/app/code/Magento/Email/Model/Template/Filter.php
@@ -51,7 +51,7 @@ class Filter extends \Magento\Framework\Filter\Template
     protected $_assetRepo;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -111,7 +111,7 @@ class Filter extends \Magento\Framework\Filter\Template
 
     /**
      * @param \Magento\Framework\Stdlib\String $string
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -127,7 +127,7 @@ class Filter extends \Magento\Framework\Filter\Template
      */
     public function __construct(
         \Magento\Framework\Stdlib\String $string,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
@@ -615,7 +615,7 @@ class Filter extends \Magento\Framework\Filter\Template
             $value = parent::filter($value);
         } catch (\Exception $e) {
             $value = '';
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return $value;
     }
diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json
index bd8e34bf0d2d6aa13a6db44fca14fdab8fd24841..5cfba4a520a15a3ca51fc72da55fed5c3e4dc450 100644
--- a/app/code/Magento/Email/composer.json
+++ b/app/code/Magento/Email/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Fedex/Model/Carrier.php b/app/code/Magento/Fedex/Model/Carrier.php
index c614c296009379b0663e930ae36b8be8bb9d5c4e..7f5c390ed91abfddae4ac393b6ab21e97813ce20 100644
--- a/app/code/Magento/Fedex/Model/Carrier.php
+++ b/app/code/Magento/Fedex/Model/Carrier.php
@@ -106,11 +106,6 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
      */
     protected $_storeManager;
 
-    /**
-     * @var \Magento\Framework\Logger
-     */
-    protected $_logger;
-
     /**
      * @var \Magento\Catalog\Model\Resource\Product\CollectionFactory
      */
@@ -119,7 +114,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
@@ -131,7 +126,6 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
      * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory
      * @param \Magento\Directory\Helper\Data $directoryData
      * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
-     * @param \Magento\Framework\Logger $logger
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Framework\Module\Dir\Reader $configReader
      * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollectionFactory
@@ -142,7 +136,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
         \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
@@ -154,7 +148,6 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
         \Magento\Directory\Model\CurrencyFactory $currencyFactory,
         \Magento\Directory\Helper\Data $directoryData,
         \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
-        \Magento\Framework\Logger $logger,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\Module\Dir\Reader $configReader,
         \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollectionFactory,
@@ -165,7 +158,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
         parent::__construct(
             $scopeConfig,
             $rateErrorFactory,
-            $logAdapterFactory,
+            $logger,
             $xmlElFactory,
             $rateFactory,
             $rateMethodFactory,
@@ -183,7 +176,6 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
         $this->_shipServiceWsdl = $wsdlBasePath . 'ShipService_v10.wsdl';
         $this->_rateServiceWsdl = $wsdlBasePath . 'RateService_v10.wsdl';
         $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v5.wsdl';
-        $this->_logger = $logger;
     }
 
     /**
@@ -459,7 +451,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
                 $debugData['result'] = $response;
             } catch (\Exception $e) {
                 $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         } else {
             $response = unserialize($response);
@@ -774,7 +766,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
                 throw new \Exception(__('Failed to parse xml document: %1', $xmlContent));
             }
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return false;
         }
     }
@@ -1038,7 +1030,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
                 $debugData['result'] = $response;
             } catch (\Exception $e) {
                 $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         } else {
             $response = unserialize($response);
diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json
index 1dfde1038b9483c7614009b9cc183ec04ebe656d..c986bb2eaa5838441677c22fce9a118d1ba457c2 100644
--- a/app/code/Magento/Fedex/composer.json
+++ b/app/code/Magento/Fedex/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json
index f3b13f068ee63bd1c7a10425d771b45639eec5b4..49c57a5c0af71c866fe7d779e0f1ba1916095910 100644
--- a/app/code/Magento/GiftMessage/composer.json
+++ b/app/code/Magento/GiftMessage/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-multishipping": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-multishipping": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GoogleAdwords/composer.json b/app/code/Magento/GoogleAdwords/composer.json
index eb6306f9fc815a14bb522b5870ae6208a578f433..788dcfae1dde7cbf9e4159876576c335a65598de 100644
--- a/app/code/Magento/GoogleAdwords/composer.json
+++ b/app/code/Magento/GoogleAdwords/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json
index 49221bfc79871e614bf95f1a6a97a386f02286f1..6970e094a645e75cd4b17a554cca3ee02fec0fa4 100644
--- a/app/code/Magento/GoogleAnalytics/composer.json
+++ b/app/code/Magento/GoogleAnalytics/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GoogleOptimizer/composer.json b/app/code/Magento/GoogleOptimizer/composer.json
index ebcb1ea65d36dfc9ee45c7630fdd280db8427904..bf78f67b5539dbbf7751efd4aed572779b692ed5 100644
--- a/app/code/Magento/GoogleOptimizer/composer.json
+++ b/app/code/Magento/GoogleOptimizer/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-google-analytics": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-google-analytics": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php
index ed8d3b3a98a690b0223dedb394f7cd4dff3921be..558a8366b6894bad5acefd25626950f02acc3270 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/ConfirmCaptcha.php
@@ -63,7 +63,7 @@ class ConfirmCaptcha extends \Magento\GoogleShopping\Controller\Adminhtml\Google
                 )
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__('Something went wrong during Captcha confirmation.'));
         }
 
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php
index 7b25e9e7c05b876038d5206113169387984202ca..d9b56660354788951409602fe7b4da31b1bd7303 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAdd.php
@@ -48,7 +48,7 @@ class MassAdd extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin
                 __('An error has occurred while adding products to google shopping account.'),
                 $e->getMessage()
             );
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             return;
         }
 
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php
index a93e723d3fc5e1aa1802f32f94a58c5fa93fad1e..8d9a12f1ee37c128a672494ec75c3879c69db97d 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/Refresh.php
@@ -55,7 +55,7 @@ class Refresh extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshoppin
                     'One or more products were not deleted from google shopping account. Refer to the log file for details.'
                 )
             );
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             return;
         }
 
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Delete.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Delete.php
index c89198bad9b5660918985c2b94b5da30321d84ef..57fc8b200a6f1766396d142c79f6b32f15d7bfcc 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Delete.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Delete.php
@@ -23,7 +23,7 @@ class Delete extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping
             }
             $this->messageManager->addSuccess(__('Attribute set mapping was deleted'));
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__("We can't delete Attribute Set Mapping."));
         }
         $this->_redirect('adminhtml/*/index', ['store' => $this->_getStore()->getId()]);
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php
index 9255b7fb806517c38903eedeb527c40f912c8d1e..1817702a5c7e073fe96776ae54c6d2ef43f23c7b 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Edit.php
@@ -43,7 +43,7 @@ class Edit extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T
             $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Google Content Attributes'));
             $this->_view->renderLayout();
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__("We can't edit Attribute Set Mapping."));
             $this->_redirect('adminhtml/*/index');
         }
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
index 2b9bdd82677da9aa009b4758ccb017b49b9afe3b..3daee5428e1cbc3c03a9e945183c679ba3e9c08b 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributeSets.php
@@ -23,7 +23,7 @@ class LoadAttributeSets extends \Magento\GoogleShopping\Controller\Adminhtml\Goo
                 )->toHtml()
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             // just need to output text with error
             $this->messageManager->addError(__("We can't load attribute sets."));
         }
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php
index 443ea921ab780c879029862ddaa7e3613d0471cf..e427a4664df17b1a48836af4a227832dfa8d4b1e 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/LoadAttributes.php
@@ -27,7 +27,7 @@ class LoadAttributes extends \Magento\GoogleShopping\Controller\Adminhtml\Google
                 )->toHtml()
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             // just need to output text with error
             $this->messageManager->addError(__("We can't load attributes."));
         }
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php
index ba47fa1415e1f4ecd1f69acc4dfc59ea74996b35..2d56b33d6674e007023ecba237362444af8554d6 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/NewAction.php
@@ -26,7 +26,7 @@ class NewAction extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopp
             $this->_view->getPage()->getConfig()->getTitle()->prepend(__('New Google Content Attribute Mapping'));
             $this->_view->renderLayout();
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__("We can't create Attribute Set Mapping."));
             $this->_redirect('adminhtml/*/index', ['store' => $this->_getStore()->getId()]);
         }
diff --git a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Save.php b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Save.php
index 0991036ac84f7be585d493a0704ba6ef90173280..f2ee9b58d4bd82206bd2ca0dd165241180e89873 100644
--- a/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Save.php
+++ b/app/code/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Types/Save.php
@@ -71,7 +71,7 @@ class Save extends \Magento\GoogleShopping\Controller\Adminhtml\Googleshopping\T
                 );
             }
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__("We can't save Attribute Set Mapping."));
         }
         $this->_redirect('adminhtml/*/index', ['store' => $this->_getStore()->getId()]);
diff --git a/app/code/Magento/GoogleShopping/Model/MassOperations.php b/app/code/Magento/GoogleShopping/Model/MassOperations.php
index 6215f00c349c7b639c7cfa394036be3f66d4d313..52c6f69d1e9d1589b76e8d45e8122332cda2201a 100644
--- a/app/code/Magento/GoogleShopping/Model/MassOperations.php
+++ b/app/code/Magento/GoogleShopping/Model/MassOperations.php
@@ -69,7 +69,7 @@ class MassOperations
      * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
      * @param \Magento\Framework\Notification\NotifierInterface $notifier
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\GoogleShopping\Helper\Data $gleShoppingData
      * @param \Magento\GoogleShopping\Helper\Category $gleShoppingCategory
      * @param array $data
@@ -80,7 +80,7 @@ class MassOperations
         \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
         \Magento\Framework\Notification\NotifierInterface $notifier,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\GoogleShopping\Helper\Data $gleShoppingData,
         \Magento\GoogleShopping\Helper\Category $gleShoppingCategory,
         array $data = []
@@ -119,7 +119,7 @@ class MassOperations
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -180,7 +180,7 @@ class MassOperations
                         $e->getMessage()
                     );
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     $errors[] = __('The product "%1" hasn\'t been added to Google Content.', $product->getName());
                 }
             }
@@ -268,7 +268,7 @@ class MassOperations
                     );
                     $totalFailed++;
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     $errors[] = __('The item "%1" hasn\'t been updated.', $item->getProduct()->getName());
                     $totalFailed++;
                 }
@@ -329,7 +329,7 @@ class MassOperations
                         $item->getProduct()
                     );
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     $errors[] = __('The item "%1" hasn\'t been deleted.', $item->getProduct()->getName());
                 }
             }
diff --git a/app/code/Magento/GoogleShopping/Model/Resource/Item/Collection.php b/app/code/Magento/GoogleShopping/Model/Resource/Item/Collection.php
index 345e68b911d80e2cd68566ccbdcff8b5c2c0d028..4b932e02a34b55bb81791fefd63e280da9a414a3 100644
--- a/app/code/Magento/GoogleShopping/Model/Resource/Item/Collection.php
+++ b/app/code/Magento/GoogleShopping/Model/Resource/Item/Collection.php
@@ -27,7 +27,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\DB\Helper $resourceHelper
@@ -37,7 +37,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\DB\Helper $resourceHelper,
diff --git a/app/code/Magento/GoogleShopping/Model/Service.php b/app/code/Magento/GoogleShopping/Model/Service.php
index 511b5d5998316c236298a199eb732e8070ab0ea0..f1a9814e9c2bda7c35486208930c4a8bbc94d4ee 100644
--- a/app/code/Magento/GoogleShopping/Model/Service.php
+++ b/app/code/Magento/GoogleShopping/Model/Service.php
@@ -32,13 +32,6 @@ class Service extends \Magento\Framework\Object
      */
     protected $_config;
 
-    /**
-     * Log adapter factory
-     *
-     * @var \Magento\Framework\Logger\AdapterFactory
-     */
-    protected $_logAdapterFactory;
-
     /**
      * Service
      * @var \Magento\Framework\Gdata\Gshopping\Content
@@ -52,25 +45,25 @@ class Service extends \Magento\Framework\Object
     protected $_contentFactory;
 
     /**
-     * Constructor
-     *
-     * By default is looking for first argument as array and assigns it as object
-     * attributes This behavior may change in child classes
-     *
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @var \Psr\Log\LoggerInterface
+     */
+    protected $logger;
+
+    /**
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\GoogleShopping\Model\Config $config
+     * @param Config $config
      * @param \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory
      * @param array $data
      */
     public function __construct(
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Registry $coreRegistry,
         \Magento\GoogleShopping\Model\Config $config,
         \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory,
         array $data = []
     ) {
-        $this->_logAdapterFactory = $logAdapterFactory;
+        $this->logger = $logger;
         $this->_coreRegistry = $coreRegistry;
         $this->_config = $config;
         $this->_contentFactory = $contentFactory;
@@ -149,12 +142,7 @@ class Service extends \Magento\Framework\Object
             $this->_service = $this->_connect($storeId);
 
             if ($this->getConfig()->getIsDebug($storeId)) {
-                $this->_service->setLogAdapter(
-                    $this->_logAdapterFactory->create(['fileName' => 'googleshopping.log']),
-                    'log'
-                )->setDebug(
-                    true
-                );
+                $this->_service->setLogAdapter($this->logger, 'debug')->setDebug(true);
             }
         }
         return $this->_service;
diff --git a/app/code/Magento/GoogleShopping/Model/Service/Item.php b/app/code/Magento/GoogleShopping/Model/Service/Item.php
index d00483fe86c40452499aeb47725e71ac4bf6dae1..857945556fc50a10973b7ace2e98b5b28bcc1723 100644
--- a/app/code/Magento/GoogleShopping/Model/Service/Item.php
+++ b/app/code/Magento/GoogleShopping/Model/Service/Item.php
@@ -24,7 +24,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
     protected $_date;
 
     /**
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Registry $coreRegistry
      * @param \Magento\GoogleShopping\Model\Config $config
      * @param \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory
@@ -33,7 +33,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
      * @param array $data
      */
     public function __construct(
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Registry $coreRegistry,
         \Magento\GoogleShopping\Model\Config $config,
         \Magento\Framework\Gdata\Gshopping\ContentFactory $contentFactory,
@@ -43,7 +43,7 @@ class Item extends \Magento\GoogleShopping\Model\Service
     ) {
         $this->_date = $date;
         $this->_googleShoppingHelper = $googleShoppingHelper;
-        parent::__construct($logAdapterFactory, $coreRegistry, $config, $contentFactory, $data);
+        parent::__construct($logger, $coreRegistry, $config, $contentFactory, $data);
     }
 
     /**
diff --git a/app/code/Magento/GoogleShopping/composer.json b/app/code/Magento/GoogleShopping/composer.json
index f7a4d09d5706628e7f6a7570996b09453bb97907..e495e5483c9d12963b8a7dbf9f10f1ee8457192d 100644
--- a/app/code/Magento/GoogleShopping/composer.json
+++ b/app/code/Magento/GoogleShopping/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GroupedImportExport/composer.json b/app/code/Magento/GroupedImportExport/composer.json
index 283e65ae98a26f3f027187bc86d81c8e6795f725..aaecfb8a7ef46a1289545908fadaf7f49303e2c9 100644
--- a/app/code/Magento/GroupedImportExport/composer.json
+++ b/app/code/Magento/GroupedImportExport/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-import-export": "0.42.0-beta1",
-        "magento/module-catalog-import-export": "0.42.0-beta1",
-        "magento/module-grouped-product": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-import-export": "0.42.0-beta2",
+        "magento/module-catalog-import-export": "0.42.0-beta2",
+        "magento/module-grouped-product": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/GroupedProduct/Controller/Adminhtml/Edit/Popup.php b/app/code/Magento/GroupedProduct/Controller/Adminhtml/Edit/Popup.php
index 5d9ffe429bddf70048592aa25424b4c75958091a..350cc7bb4414883212ca006f73128945470b4f45 100644
--- a/app/code/Magento/GroupedProduct/Controller/Adminhtml/Edit/Popup.php
+++ b/app/code/Magento/GroupedProduct/Controller/Adminhtml/Edit/Popup.php
@@ -18,7 +18,7 @@ class Popup extends \Magento\Backend\App\AbstractAction
     protected $factory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -26,13 +26,13 @@ class Popup extends \Magento\Backend\App\AbstractAction
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Catalog\Model\ProductFactory $factory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Catalog\Model\ProductFactory $factory,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->registry = $registry;
         $this->factory = $factory;
@@ -74,7 +74,7 @@ class Popup extends \Magento\Backend\App\AbstractAction
                 $product->load($productId);
             } catch (\Exception $e) {
                 $product->setTypeId(\Magento\Catalog\Model\Product\Type::DEFAULT_TYPE);
-                $this->logger->logException($e);
+                $this->logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
index 34a82a60b5c13b01ea5ca56b1ad0d3eba12feb46..4a6f83b3ffd02087eaec2adcec53bf2b3228c71a 100644
--- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
+++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php
@@ -88,7 +88,7 @@ class Grouped extends \Magento\Catalog\Model\Product\Type\AbstractType
      * @param \Magento\Core\Helper\File\Storage\Database $fileStorageDb
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param ProductRepositoryInterface $productRepository
      * @param \Magento\GroupedProduct\Model\Resource\Product\Link $catalogProductLink
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -107,7 +107,7 @@ class Grouped extends \Magento\Catalog\Model\Product\Type\AbstractType
         \Magento\Core\Helper\File\Storage\Database $fileStorageDb,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         ProductRepositoryInterface $productRepository,
         \Magento\GroupedProduct\Model\Resource\Product\Link $catalogProductLink,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/GroupedProduct/Model/Resource/Product/Type/Grouped/AssociatedProductsCollection.php b/app/code/Magento/GroupedProduct/Model/Resource/Product/Type/Grouped/AssociatedProductsCollection.php
index 923420bb700d0af8b30df921acb60a3419503649..c66cd3d23f38bd9054893e690d451666cc1ac963 100644
--- a/app/code/Magento/GroupedProduct/Model/Resource/Product/Type/Grouped/AssociatedProductsCollection.php
+++ b/app/code/Magento/GroupedProduct/Model/Resource/Product/Type/Grouped/AssociatedProductsCollection.php
@@ -27,7 +27,7 @@ class AssociatedProductsCollection extends \Magento\Catalog\Model\Resource\Produ
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -53,7 +53,7 @@ class AssociatedProductsCollection extends \Magento\Catalog\Model\Resource\Produ
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/GroupedProduct/composer.json b/app/code/Magento/GroupedProduct/composer.json
index 781192913139b86f6c0dd41fdc00d24ba015f907..ed6dc4ddd57ef1fb2e43b71e8ec2df561c347fce 100644
--- a/app/code/Magento/GroupedProduct/composer.json
+++ b/app/code/Magento/GroupedProduct/composer.json
@@ -3,21 +3,21 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-msrp": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-msrp": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/Export.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/Export.php
index d53388494c7a8471ac6a6484714164ce73ee12fe..1ed8b3eb9e2fb36cbe09ebd1b8fb34d868aa844e 100644
--- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/Export.php
+++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/Export.php
@@ -48,7 +48,7 @@ class Export extends \Magento\ImportExport\Controller\Adminhtml\Export
             } catch (\Magento\Framework\Model\Exception $e) {
                 $this->messageManager->addError($e->getMessage());
             } catch (\Exception $e) {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->messageManager->addError(__('Please correct the data sent.'));
             }
         } else {
diff --git a/app/code/Magento/ImportExport/Model/AbstractModel.php b/app/code/Magento/ImportExport/Model/AbstractModel.php
index ca62620295ef0ca1c32cc4d4ab849e697e5dfb1e..987884e46fabcf9cd3518ec94ea46c809e8a77a0 100644
--- a/app/code/Magento/ImportExport/Model/AbstractModel.php
+++ b/app/code/Magento/ImportExport/Model/AbstractModel.php
@@ -20,12 +20,6 @@ abstract class AbstractModel extends \Magento\Framework\Object
      */
     protected $_debugMode = false;
 
-    /**
-     * Logger instance
-     * @var \Magento\Framework\Logger\Adapter
-     */
-    protected $_logInstance;
-
     /**
      * Fields that should be replaced in debug with '***'
      *
@@ -41,7 +35,7 @@ abstract class AbstractModel extends \Magento\Framework\Object
     protected $_logTrace = [];
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -51,25 +45,17 @@ abstract class AbstractModel extends \Magento\Framework\Object
     protected $_varDirectory;
 
     /**
-     * @var \Magento\Framework\Logger\AdapterFactory
-     */
-    protected $_adapterFactory;
-
-    /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
-     * @param \Magento\Framework\Logger\AdapterFactory $adapterFactory
      * @param array $data
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
-        \Magento\Framework\Logger\AdapterFactory $adapterFactory,
         array $data = []
     ) {
         $this->_logger = $logger;
         $this->_varDirectory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
-        $this->_adapterFactory = $adapterFactory;
         parent::__construct($data);
     }
 
@@ -87,32 +73,11 @@ abstract class AbstractModel extends \Magento\Framework\Object
         } else {
             $this->_logTrace[] = $debugData;
         }
-        if (!$this->_debugMode) {
-            return $this;
-        }
 
-        if (!$this->_logInstance) {
-            $dirName = date('Y/m/d/');
-            $fileName = join(
-                '_',
-                [
-                    str_replace(':', '-', $this->getRunAt()),
-                    $this->getScheduledOperationId(),
-                    $this->getOperationType(),
-                    $this->getEntity()
-                ]
-            );
-            $path = 'import_export/' . $dirName;
-            $this->_varDirectory->create($path);
-
-            $fileName = $path . $fileName . '.log';
-            $this->_logInstance = $this->_adapterFactory->create(
-                ['fileName' => $this->_varDirectory->getAbsolutePath($fileName)]
-            )->setFilterDataKeys(
-                $this->_debugReplacePrivateDataKeys
-            );
+        if ($this->_debugMode) {
+            $this->_logger->debug($debugData);
         }
-        $this->_logInstance->log($debugData);
+
         return $this;
     }
 
diff --git a/app/code/Magento/ImportExport/Model/Export.php b/app/code/Magento/ImportExport/Model/Export.php
index e31fe45df3ddae4c4bcac40588ade572cb1fdc2f..d4555391afd3db51ff40733ae9acb0998a82fc66 100644
--- a/app/code/Magento/ImportExport/Model/Export.php
+++ b/app/code/Magento/ImportExport/Model/Export.php
@@ -56,18 +56,16 @@ class Export extends \Magento\ImportExport\Model\AbstractModel
     protected $_exportAdapterFac;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
-     * @param \Magento\Framework\Logger\AdapterFactory $adapterFactory
      * @param \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig
      * @param \Magento\ImportExport\Model\Export\Entity\Factory $entityFactory
      * @param \Magento\ImportExport\Model\Export\Adapter\Factory $exportAdapterFac
      * @param array $data
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
-        \Magento\Framework\Logger\AdapterFactory $adapterFactory,
         \Magento\ImportExport\Model\Export\ConfigInterface $exportConfig,
         \Magento\ImportExport\Model\Export\Entity\Factory $entityFactory,
         \Magento\ImportExport\Model\Export\Adapter\Factory $exportAdapterFac,
@@ -76,7 +74,7 @@ class Export extends \Magento\ImportExport\Model\AbstractModel
         $this->_exportConfig = $exportConfig;
         $this->_entityFactory = $entityFactory;
         $this->_exportAdapterFac = $exportAdapterFac;
-        parent::__construct($logger, $filesystem, $adapterFactory, $data);
+        parent::__construct($logger, $filesystem, $data);
     }
 
     /**
@@ -94,7 +92,7 @@ class Export extends \Magento\ImportExport\Model\AbstractModel
                 try {
                     $this->_entityAdapter = $this->_entityFactory->create($entities[$this->getEntity()]['model']);
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     throw new \Magento\Framework\Model\Exception(__('Please enter a correct entity model'));
                 }
                 if (!$this->_entityAdapter instanceof \Magento\ImportExport\Model\Export\Entity\AbstractEntity &&
@@ -138,7 +136,7 @@ class Export extends \Magento\ImportExport\Model\AbstractModel
                 try {
                     $this->_writer = $this->_exportAdapterFac->create($fileFormats[$this->getFileFormat()]['model']);
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     throw new \Magento\Framework\Model\Exception(__('Please enter a correct entity model'));
                 }
                 if (!$this->_writer instanceof \Magento\ImportExport\Model\Export\Adapter\AbstractAdapter) {
diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php
index 6b5900c9b8f384fbffed19b38aabb52c9ff17000..37f63e1ce2978b02343a42855f2a634802f175ac 100644
--- a/app/code/Magento/ImportExport/Model/Import.php
+++ b/app/code/Magento/ImportExport/Model/Import.php
@@ -110,9 +110,8 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
     protected $_filesystem;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
-     * @param \Magento\Framework\Logger\AdapterFactory $adapterFactory
      * @param \Magento\ImportExport\Helper\Data $importExportData
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig
      * @param Import\ConfigInterface $importConfig
@@ -126,9 +125,8 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
      * @param array $data
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
-        \Magento\Framework\Logger\AdapterFactory $adapterFactory,
         \Magento\ImportExport\Helper\Data $importExportData,
         \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig,
         \Magento\ImportExport\Model\Import\ConfigInterface $importConfig,
@@ -152,7 +150,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
         $this->indexerRegistry = $indexerRegistry;
         $this->_behaviorFactory = $behaviorFactory;
         $this->_filesystem = $filesystem;
-        parent::__construct($logger, $filesystem, $adapterFactory, $data);
+        parent::__construct($logger, $filesystem, $data);
     }
 
     /**
@@ -170,7 +168,7 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
                 try {
                     $this->_entityAdapter = $this->_entityFactory->create($entities[$this->getEntity()]['model']);
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     throw new \Magento\Framework\Model\Exception(__('Please enter a correct entity model'));
                 }
                 if (!$this->_entityAdapter instanceof \Magento\ImportExport\Model\Import\Entity\AbstractEntity &&
diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json
index 51959b208707d79adfdbacced84a4f722753c5cc..0333fadc33c60317361d01ab544918358e5b7233 100644
--- a/app/code/Magento/ImportExport/composer.json
+++ b/app/code/Magento/ImportExport/composer.json
@@ -3,17 +3,17 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-indexer": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-indexer": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "ext-ctype": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Indexer/composer.json b/app/code/Magento/Indexer/composer.json
index 16531f086231b9ef8eced6bc4016591451c1561a..1a2e3bcba0755af746f51f19f35de036f2c3cbb2 100644
--- a/app/code/Magento/Indexer/composer.json
+++ b/app/code/Magento/Indexer/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-page-cache": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
index 8e8b39726f7aa6506edddd84ef3cb37ae6354d3d..2e1acd132001d7a6f11a4760af2c64791fdd93ef 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
@@ -27,7 +27,7 @@ class Integration extends Action
      */
     protected $_registry;
 
-    /** @var \Magento\Framework\Logger */
+    /** @var \Psr\Log\LoggerInterface */
     protected $_logger;
 
     /** @var \Magento\Integration\Service\V1\IntegrationInterface */
@@ -53,7 +53,7 @@ class Integration extends Action
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Registry $registry
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService
      * @param IntegrationOauthService $oauthService
      * @param \Magento\Core\Helper\Data $coreHelper
@@ -64,7 +64,7 @@ class Integration extends Action
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Framework\Registry $registry,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Integration\Service\V1\IntegrationInterface $integrationService,
         IntegrationOauthService $oauthService,
         \Magento\Core\Helper\Data $coreHelper,
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Delete.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Delete.php
index 809323333ca0468282167a5363b2b0a802ef87d3..cc56199c514768901e16db7906d57930648de537 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Delete.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Delete.php
@@ -52,7 +52,7 @@ class Delete extends \Magento\Integration\Controller\Adminhtml\Integration
         } catch (\Magento\Integration\Exception $e) {
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         $this->_redirect('*/*/');
     }
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Edit.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Edit.php
index f7523b7c4bfafc80efd2d21cfc67520539c8a69a..52254b3be871968c44ccd583ce9ad8eff5cce426 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Edit.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Edit.php
@@ -29,7 +29,7 @@ class Edit extends \Magento\Integration\Controller\Adminhtml\Integration
                 $this->_redirect('*/*/');
                 return;
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 $this->messageManager->addError(__('Internal error. Check exception log for details.'));
                 $this->_redirect('*/*');
                 return;
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/PermissionsDialog.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/PermissionsDialog.php
index 40c30063f95726935eed857948fe0a4861369f30..8169abfebef32918f4f13e94617d81f7bfbed076 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/PermissionsDialog.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/PermissionsDialog.php
@@ -26,7 +26,7 @@ class PermissionsDialog extends \Magento\Integration\Controller\Adminhtml\Integr
                 $this->_redirect('*/*/');
                 return;
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 $this->messageManager->addError(__('Internal error. Check exception log for details.'));
                 $this->_redirect('*/*');
                 return;
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
index 2f580567c2b8815ae2be22b62c1c2dd38da5e092..309b2b80699346bb5274eb0fa632b914a6c0c5c3 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
@@ -46,7 +46,7 @@ class Save extends \Magento\Integration\Controller\Adminhtml\Integration
                     $this->_redirect('*/*/');
                     return;
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                     $this->messageManager->addError(__('Internal error. Check exception log for details.'));
                     $this->_redirect('*/*');
                     return;
@@ -94,7 +94,7 @@ class Save extends \Magento\Integration\Controller\Adminhtml\Integration
             $this->messageManager->addError($this->escaper->escapeHtml($e->getMessage()));
             $this->_redirectOnSaveError();
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             $this->messageManager->addError($this->escaper->escapeHtml($e->getMessage()));
             $this->_redirectOnSaveError();
         }
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensDialog.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensDialog.php
index 15cd3f85fc90cb68e5da1c4f50c6a1d884784975..f8747958f2cf44a99bb81da64857d23e0404ecac 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensDialog.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensDialog.php
@@ -53,7 +53,7 @@ class TokensDialog extends \Magento\Integration\Controller\Adminhtml\Integration
             $this->_redirect('*/*');
             return;
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             $this->messageManager->addError(__('Internal error. Check exception log for details.'));
             $this->_redirect('*/*');
             return;
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php
index 7ddd5e935f1ddd35a1d6de2a1a94aff7e4760bb9..342b198336c4afd292f7e40d16c137720fcd1dda 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php
@@ -64,7 +64,7 @@ class TokensExchange extends \Magento\Integration\Controller\Adminhtml\Integrati
             $this->_redirect('*/*');
             return;
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             $this->messageManager->addError(__('Internal error. Check exception log for details.'));
             $this->_redirect('*/*');
             return;
diff --git a/app/code/Magento/Integration/Model/Oauth/Token/Factory.php b/app/code/Magento/Integration/Model/Oauth/Token/Factory.php
deleted file mode 100644
index 0ef69a3d4e154bcb3b8144d48b1b8c696d85789b..0000000000000000000000000000000000000000
--- a/app/code/Magento/Integration/Model/Oauth/Token/Factory.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-namespace Magento\Integration\Model\Oauth\Token;
-
-/**
- * Token builder factory
- */
-class Factory
-{
-    /**
-     * @var \Magento\Framework\ObjectManagerInterface
-     */
-    protected $_objectManager;
-
-    /**
-     * @param \Magento\Framework\ObjectManagerInterface $objectManager
-     */
-    public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
-    {
-        $this->_objectManager = $objectManager;
-    }
-
-    /**
-     * Create token model.
-     *
-     * @param array $arguments
-     * @return \Magento\Integration\Model\Oauth\Token
-     */
-    public function create($arguments = [])
-    {
-        return $this->_objectManager->create('Magento\Integration\Model\Oauth\Token', $arguments);
-    }
-}
diff --git a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
index e4a0d7134d7de936066f12849dc7fc472c58f2cd..54938d57a21c6c1fa203423baff6945dbf0bc763 100644
--- a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
+++ b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
@@ -17,7 +17,7 @@ class Provider implements TokenProviderInterface
     protected $_consumerFactory;
 
     /**
-     * @var \Magento\Integration\Model\Oauth\Token\Factory
+     * @var \Magento\Integration\Model\Oauth\TokenFactory
      */
     protected $_tokenFactory;
 
@@ -31,30 +31,22 @@ class Provider implements TokenProviderInterface
      */
     protected $_date;
 
-    /**
-     * @var Token
-     */
-    protected $token;
-
     /**
      * @param \Magento\Integration\Model\Oauth\Consumer\Factory $consumerFactory
-     * @param \Magento\Integration\Model\Oauth\Token\Factory $tokenFactory
+     * @param \Magento\Integration\Model\Oauth\TokenFactory $tokenFactory
      * @param \Magento\Integration\Helper\Oauth\Data $dataHelper
      * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
-     * @param Token $token
      */
     public function __construct(
         \Magento\Integration\Model\Oauth\Consumer\Factory $consumerFactory,
-        \Magento\Integration\Model\Oauth\Token\Factory $tokenFactory,
+        \Magento\Integration\Model\Oauth\TokenFactory $tokenFactory,
         \Magento\Integration\Helper\Oauth\Data $dataHelper,
-        \Magento\Framework\Stdlib\DateTime\DateTime $date,
-        Token $token
+        \Magento\Framework\Stdlib\DateTime\DateTime $date
     ) {
         $this->_consumerFactory = $consumerFactory;
         $this->_tokenFactory = $tokenFactory;
         $this->_dataHelper = $dataHelper;
         $this->_date = $date;
-        $this->token = $token;
     }
 
     /**
@@ -293,7 +285,9 @@ class Provider implements TokenProviderInterface
      */
     public function getIntegrationTokenByConsumerId($consumerId)
     {
-        $token = $this->token->loadByConsumerIdAndUserType($consumerId, UserContextInterface::USER_TYPE_INTEGRATION);
+        /** @var \Magento\Integration\Model\Oauth\Token $token */
+        $token = $this->_tokenFactory->create();
+        $token->loadByConsumerIdAndUserType($consumerId, UserContextInterface::USER_TYPE_INTEGRATION);
 
         if (!$token->getId()) {
             throw new \Magento\Framework\Oauth\Exception(
diff --git a/app/code/Magento/Integration/Service/V1/AdminTokenService.php b/app/code/Magento/Integration/Service/V1/AdminTokenService.php
index 06d08c2995dbca6cd5bdc9f850ca6f92e6e3f62a..4629800f46fdefac551322ff5d8908abb1c059b1 100644
--- a/app/code/Magento/Integration/Service/V1/AdminTokenService.php
+++ b/app/code/Magento/Integration/Service/V1/AdminTokenService.php
@@ -9,7 +9,7 @@ use Magento\Framework\Exception\AuthenticationException;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Integration\Helper\Validator;
 use Magento\Integration\Model\Oauth\Token as Token;
-use Magento\Integration\Model\Oauth\Token\Factory as TokenModelFactory;
+use Magento\Integration\Model\Oauth\TokenFactory as TokenModelFactory;
 use Magento\Integration\Model\Resource\Oauth\Token\CollectionFactory as TokenCollectionFactory;
 use Magento\User\Model\User as UserModel;
 
diff --git a/app/code/Magento/Integration/Service/V1/AuthorizationService.php b/app/code/Magento/Integration/Service/V1/AuthorizationService.php
index 177ba061c5aee04d5b3af787b14ac25ad63a6119..b6aed4022ff57836428c87d6d371b8325fdf4660 100644
--- a/app/code/Magento/Integration/Service/V1/AuthorizationService.php
+++ b/app/code/Magento/Integration/Service/V1/AuthorizationService.php
@@ -15,7 +15,7 @@ use Magento\Framework\Acl;
 use Magento\Framework\Acl\Builder as AclBuilder;
 use Magento\Framework\Acl\RootResource as RootAclResource;
 use Magento\Framework\Exception\LocalizedException;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Service for integration permissions management.
@@ -101,7 +101,7 @@ class AuthorizationService implements AuthorizationServiceInterface
             }
             $this->_associateResourcesWithRole($role, $resources);
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw new LocalizedException('Error happened while granting permissions. Check exception log for details.');
         }
     }
@@ -122,7 +122,7 @@ class AuthorizationService implements AuthorizationServiceInterface
         try {
             $this->_deleteRole($integrationId);
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw new LocalizedException(
                 'Error happened while deleting role and permissions. Check exception log for details.'
             );
diff --git a/app/code/Magento/Integration/Service/V1/CustomerTokenService.php b/app/code/Magento/Integration/Service/V1/CustomerTokenService.php
index 6d1c08cefd3c65d46588bb2d4be485f7aa5c4392..d37e29101417ba0aa8d8138303dd9992a75eea6f 100644
--- a/app/code/Magento/Integration/Service/V1/CustomerTokenService.php
+++ b/app/code/Magento/Integration/Service/V1/CustomerTokenService.php
@@ -9,7 +9,7 @@ use Magento\Customer\Api\AccountManagementInterface;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Integration\Helper\Validator;
 use Magento\Integration\Model\Oauth\Token as Token;
-use Magento\Integration\Model\Oauth\Token\Factory as TokenModelFactory;
+use Magento\Integration\Model\Oauth\TokenFactory as TokenModelFactory;
 use Magento\Integration\Model\Resource\Oauth\Token\CollectionFactory as TokenCollectionFactory;
 
 class CustomerTokenService implements CustomerTokenServiceInterface
diff --git a/app/code/Magento/Integration/Service/V1/Oauth.php b/app/code/Magento/Integration/Service/V1/Oauth.php
index c3c9e30e9e0bd7063f6e188fc2054942a3a9cc05..d4bbe6fd4cef27643a66be967088a10f252bb2df 100644
--- a/app/code/Magento/Integration/Service/V1/Oauth.php
+++ b/app/code/Magento/Integration/Service/V1/Oauth.php
@@ -9,7 +9,7 @@ use Magento\Integration\Helper\Oauth\Data as IntegrationOauthHelper;
 use Magento\Integration\Model\Oauth\Consumer as ConsumerModel;
 use Magento\Integration\Model\Oauth\Consumer\Factory as ConsumerFactory;
 use Magento\Integration\Model\Oauth\Token as OauthTokenModel;
-use Magento\Integration\Model\Oauth\Token\Factory as TokenFactory;
+use Magento\Integration\Model\Oauth\TokenFactory as TokenFactory;
 use Magento\Integration\Model\Oauth\Token\Provider as TokenProvider;
 
 /**
@@ -46,7 +46,7 @@ class Oauth implements OauthInterface
     protected $_httpClient;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -68,7 +68,7 @@ class Oauth implements OauthInterface
      * @param TokenFactory $tokenFactory
      * @param IntegrationOauthHelper $dataHelper
      * @param \Magento\Framework\HTTP\ZendClient $httpClient
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param OauthHelper $oauthHelper
      * @param TokenProvider $tokenProvider
      */
@@ -78,7 +78,7 @@ class Oauth implements OauthInterface
         TokenFactory $tokenFactory,
         IntegrationOauthHelper $dataHelper,
         \Magento\Framework\HTTP\ZendClient $httpClient,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         OauthHelper $oauthHelper,
         TokenProvider $tokenProvider
     ) {
@@ -220,7 +220,7 @@ class Oauth implements OauthInterface
         } catch (\Magento\Framework\Oauth\Exception $exception) {
             throw $exception;
         } catch (\Exception $exception) {
-            $this->_logger->logException($exception);
+            $this->_logger->critical($exception);
             throw new \Magento\Framework\Oauth\Exception(
                 'Unable to post data to consumer due to an unexpected error'
             );
diff --git a/app/code/Magento/Integration/composer.json b/app/code/Magento/Integration/composer.json
index a519797a8eab07172155c6e2fe5cf83768fdfd55..d30a365c4c99178ac1fa77214b23b17aa5002f22 100644
--- a/app/code/Magento/Integration/composer.json
+++ b/app/code/Magento/Integration/composer.json
@@ -3,17 +3,17 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-user": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-authorization": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-user": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-authorization": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/LayeredNavigation/composer.json b/app/code/Magento/LayeredNavigation/composer.json
index de31b81e34d0056725f4b876fab00fdea88226f3..aadf43d71c1d2a0b6655b97d5dfe9ee34cf62e7e 100644
--- a/app/code/Magento/LayeredNavigation/composer.json
+++ b/app/code/Magento/LayeredNavigation/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Log/Model/Resource/Visitor/Online/Collection.php b/app/code/Magento/Log/Model/Resource/Visitor/Online/Collection.php
index cfdaae9d44bfcaf0dbc35466cac34e8a62c7b29b..f0188880781d8a24614e125f5b4f1ebf162aa4a8 100644
--- a/app/code/Magento/Log/Model/Resource/Visitor/Online/Collection.php
+++ b/app/code/Magento/Log/Model/Resource/Visitor/Online/Collection.php
@@ -25,7 +25,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Helper\Data $eavHelper
@@ -34,7 +34,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Helper\Data $eavHelper,
diff --git a/app/code/Magento/Log/Model/Resource/Visitor/Online/Grid/Collection.php b/app/code/Magento/Log/Model/Resource/Visitor/Online/Grid/Collection.php
index 32971b43e8dfcf45a4935180d5fba9558a473356..43ad11917851cd5cfa32f66fc5ff88c63f721df6 100644
--- a/app/code/Magento/Log/Model/Resource/Visitor/Online/Grid/Collection.php
+++ b/app/code/Magento/Log/Model/Resource/Visitor/Online/Grid/Collection.php
@@ -15,7 +15,7 @@ class Collection extends \Magento\Log\Model\Resource\Visitor\Online\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Helper\Data $eavHelper
@@ -25,7 +25,7 @@ class Collection extends \Magento\Log\Model\Resource\Visitor\Online\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Helper\Data $eavHelper,
diff --git a/app/code/Magento/Log/Model/Visitor.php b/app/code/Magento/Log/Model/Visitor.php
index 079e1dd97759db12bdb091b166d711940e4386a8..ea33af37a292a55e6177622df16225b0204153e3 100644
--- a/app/code/Magento/Log/Model/Visitor.php
+++ b/app/code/Magento/Log/Model/Visitor.php
@@ -209,7 +209,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel
                 $visitor->setData($this->getData());
             }
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return $this;
     }
diff --git a/app/code/Magento/Log/composer.json b/app/code/Magento/Log/composer.json
index baa3748cbdd0ff62be87f31d3b69e6991b329212..9f97050e77e98efd8d082b033c26326cc388fdbb 100644
--- a/app/code/Magento/Log/composer.json
+++ b/app/code/Magento/Log/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json
index 7203cd93a371b57e77afc3d581ff592116fc4c31..4644a21f2c486a20dadd542b2e7d4f9baeb65cbf 100644
--- a/app/code/Magento/Msrp/composer.json
+++ b/app/code/Magento/Msrp/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-bundle": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-downloadable": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-grouped-product": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-bundle": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-downloadable": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-grouped-product": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Multishipping/Controller/Checkout/Overview.php b/app/code/Magento/Multishipping/Controller/Checkout/Overview.php
index a49a02698a29986a870c5f2c27df0024810fd104..23474bac028c964372ed0f63321a2f3de5263cc8 100644
--- a/app/code/Magento/Multishipping/Controller/Checkout/Overview.php
+++ b/app/code/Magento/Multishipping/Controller/Checkout/Overview.php
@@ -41,7 +41,7 @@ class Overview extends \Magento\Multishipping\Controller\Checkout
             $this->messageManager->addError($e->getMessage());
             $this->_redirect('*/*/billing');
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addException($e, __('We cannot open the overview page.'));
             $this->_redirect('*/*/billing');
         }
diff --git a/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php b/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
index 1549d894a76a4f2f02c202319c375b4053f67c0b..22b3cad9e9a88664339df5377634217d1b3abb39 100644
--- a/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
+++ b/app/code/Magento/Multishipping/Controller/Checkout/OverviewPost.php
@@ -105,7 +105,7 @@ class OverviewPost extends \Magento\Multishipping\Controller\Checkout
             $this->messageManager->addError($e->getMessage());
             $this->_redirect('*/*/billing');
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_objectManager->get(
                 'Magento\Checkout\Helper\Data'
             )->sendPaymentFailedEmail(
diff --git a/app/code/Magento/Multishipping/composer.json b/app/code/Magento/Multishipping/composer.json
index 5ac026eaacb8ecb85386d62854e7c0064a293389..4b6f7bd24aca01dee81cdb52e250f3ff4e5e19bc 100644
--- a/app/code/Magento/Multishipping/composer.json
+++ b/app/code/Magento/Multishipping/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Newsletter/Model/Resource/Problem/Collection.php b/app/code/Magento/Newsletter/Model/Resource/Problem/Collection.php
index 2725043fc129aef75815329386056c4b428a5278..57fbf47df91360a3c19b7b565eaf49995fba62d6 100644
--- a/app/code/Magento/Newsletter/Model/Resource/Problem/Collection.php
+++ b/app/code/Magento/Newsletter/Model/Resource/Problem/Collection.php
@@ -56,7 +56,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param CustomerRepository $customerRepository
@@ -66,7 +66,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         CustomerRepository $customerRepository,
diff --git a/app/code/Magento/Newsletter/Model/Resource/Queue/Collection.php b/app/code/Magento/Newsletter/Model/Resource/Queue/Collection.php
index c967aa6e7ba393de6207e9e9e500494e4488ec1f..99ad006db65e13ca960f04422f9561b6bb375db0 100644
--- a/app/code/Magento/Newsletter/Model/Resource/Queue/Collection.php
+++ b/app/code/Magento/Newsletter/Model/Resource/Queue/Collection.php
@@ -34,7 +34,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
@@ -43,7 +43,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Stdlib\DateTime\DateTime $date,
diff --git a/app/code/Magento/Newsletter/Model/Resource/Subscriber/Collection.php b/app/code/Magento/Newsletter/Model/Resource/Subscriber/Collection.php
index 6b405f08c38624878c5474f3d78b9dae2f6bd04a..1da9cb8fd70a0c6d69ebefbbcc0a87207aecf7b6 100644
--- a/app/code/Magento/Newsletter/Model/Resource/Subscriber/Collection.php
+++ b/app/code/Magento/Newsletter/Model/Resource/Subscriber/Collection.php
@@ -57,7 +57,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Helper\Data $customerHelperData
@@ -66,7 +66,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Helper\Data $customerHelperData,
diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php
index c0b2d96137ac3d5ccffe02f76087acd99fcf6c87..1a29809a3374c527e4935afc100e37783b8abcd7 100644
--- a/app/code/Magento/Newsletter/Model/Subscriber.php
+++ b/app/code/Magento/Newsletter/Model/Subscriber.php
@@ -583,7 +583,7 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel
                 }
             } catch (MailException $e) {
                 // If we are not able to send a new account email, this should be ignored
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
             }
         }
         return $this;
diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json
index 06d75d0352e700275288937dc80675400ff3756e..8e8c5ea8d79ba4c157fc69a08bd6cf640a9d1974 100644
--- a/app/code/Magento/Newsletter/composer.json
+++ b/app/code/Magento/Newsletter/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-email": "0.42.0-beta1",
-        "magento/module-cron": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-email": "0.42.0-beta2",
+        "magento/module-cron": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/OfflinePayments/Model/Banktransfer.php b/app/code/Magento/OfflinePayments/Model/Banktransfer.php
index fb8d31b9c90f378aa80868c318e90d6794861ade..858f68ddc21c5f1881129010d1a389282ef5db9f 100644
--- a/app/code/Magento/OfflinePayments/Model/Banktransfer.php
+++ b/app/code/Magento/OfflinePayments/Model/Banktransfer.php
@@ -32,6 +32,13 @@ class Banktransfer extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_infoBlockType = 'Magento\Payment\Block\Info\Instructions';
 
+    /**
+     * Availability option
+     *
+     * @var bool
+     */
+    protected $_isOffline = true;
+
     /**
      * Get instructions text from config
      *
diff --git a/app/code/Magento/OfflinePayments/Model/Cashondelivery.php b/app/code/Magento/OfflinePayments/Model/Cashondelivery.php
index 74097a82728688af1fb18a4e8a33ab027bbb1959..07ca59f6ac74829f0b2e943ef59c903819e5bbbb 100644
--- a/app/code/Magento/OfflinePayments/Model/Cashondelivery.php
+++ b/app/code/Magento/OfflinePayments/Model/Cashondelivery.php
@@ -30,6 +30,13 @@ class Cashondelivery extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_infoBlockType = 'Magento\Payment\Block\Info\Instructions';
 
+    /**
+     * Availability option
+     *
+     * @var bool
+     */
+    protected $_isOffline = true;
+
     /**
      * Get instructions text from config
      *
diff --git a/app/code/Magento/OfflinePayments/Model/Checkmo.php b/app/code/Magento/OfflinePayments/Model/Checkmo.php
index 4b1bc2b0558421442357a3f48c1698045cb41875..37a8e7a3e20ccac918afb69218f6b774d1b7b102 100644
--- a/app/code/Magento/OfflinePayments/Model/Checkmo.php
+++ b/app/code/Magento/OfflinePayments/Model/Checkmo.php
@@ -21,6 +21,13 @@ class Checkmo extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_infoBlockType = 'Magento\OfflinePayments\Block\Info\Checkmo';
 
+    /**
+     * Availability option
+     *
+     * @var bool
+     */
+    protected $_isOffline = true;
+
     /**
      * Assign data to info model instance
      *
diff --git a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php
index d41a3cdbf77ccc8fbd145243a6742d3addda76e3..0c82a6352f44a227a0b31f7108aa2299f0e37c6d 100644
--- a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php
+++ b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php
@@ -21,6 +21,13 @@ class Purchaseorder extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_infoBlockType = 'Magento\OfflinePayments\Block\Info\Purchaseorder';
 
+    /**
+     * Availability option
+     *
+     * @var bool
+     */
+    protected $_isOffline = true;
+
     /**
      * Assign data to info model instance
      *
diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json
index 42c64fde731c41b645039309920c6c479f615102..3e14de61e13f879d56f10528e261c75b2a207470 100644
--- a/app/code/Magento/OfflinePayments/composer.json
+++ b/app/code/Magento/OfflinePayments/composer.json
@@ -3,12 +3,12 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Flatrate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Flatrate.php
index 76e0436d79118635ad3750b97f714aca43901e6d..559102029f395fc87912f5226ed104009f1e6afc 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Flatrate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Flatrate.php
@@ -35,7 +35,7 @@ class Flatrate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implement
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
      * @param array $data
@@ -43,14 +43,14 @@ class Flatrate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implement
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
         array $data = []
     ) {
         $this->_rateResultFactory = $rateResultFactory;
         $this->_rateMethodFactory = $rateMethodFactory;
-        parent::__construct($scopeConfig, $rateErrorFactory, $logAdapterFactory, $data);
+        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
     }
 
     /**
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Freeshipping.php b/app/code/Magento/OfflineShipping/Model/Carrier/Freeshipping.php
index 0e9274eb72644706d6351adba09a8c031f8ac174..5fac8565babe68fbeeddc2efb95621281c2510b2 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Freeshipping.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Freeshipping.php
@@ -36,7 +36,7 @@ class Freeshipping extends \Magento\Shipping\Model\Carrier\AbstractCarrier imple
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
      * @param array $data
@@ -44,14 +44,14 @@ class Freeshipping extends \Magento\Shipping\Model\Carrier\AbstractCarrier imple
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
         array $data = []
     ) {
         $this->_rateResultFactory = $rateResultFactory;
         $this->_rateMethodFactory = $rateMethodFactory;
-        parent::__construct($scopeConfig, $rateErrorFactory, $logAdapterFactory, $data);
+        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
     }
 
     /**
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Pickup.php b/app/code/Magento/OfflineShipping/Model/Carrier/Pickup.php
index 16a86670b815c27c12b2e9f76d3c3c48330f5d13..d689bef7b956743e395dc8c406e3f29ffaca2e67 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Pickup.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Pickup.php
@@ -30,7 +30,7 @@ class Pickup extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
      * @param array $data
@@ -38,14 +38,14 @@ class Pickup extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
         array $data = []
     ) {
         $this->_rateResultFactory = $rateResultFactory;
         $this->_rateMethodFactory = $rateMethodFactory;
-        parent::__construct($scopeConfig, $rateErrorFactory, $logAdapterFactory, $data);
+        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
     }
 
     /**
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
index 60cb1f3faa31754161d4252a53b72e74ad34e810..710c6b45ff3d3f630d6c267038d3e21934a07e1a 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
@@ -45,7 +45,7 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory
      * @param \Magento\OfflineShipping\Model\Resource\Carrier\TablerateFactory $tablerateFactory
@@ -54,7 +54,7 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory,
         \Magento\OfflineShipping\Model\Resource\Carrier\TablerateFactory $tablerateFactory,
@@ -63,7 +63,7 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
         $this->_rateResultFactory = $rateResultFactory;
         $this->_resultMethodFactory = $resultMethodFactory;
         $this->_tablerateFactory = $tablerateFactory;
-        parent::__construct($scopeConfig, $rateErrorFactory, $logAdapterFactory, $data);
+        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
         foreach ($this->getCode('condition_name') as $k => $v) {
             $this->_conditionNames[] = $k;
         }
diff --git a/app/code/Magento/OfflineShipping/Model/Resource/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Resource/Carrier/Tablerate.php
index 9b019fd194de8d4b9399ddaa5712882dca3930f0..ee3d001166fe36c91e84a81052a41899959b1b7a 100644
--- a/app/code/Magento/OfflineShipping/Model/Resource/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Resource/Carrier/Tablerate.php
@@ -85,7 +85,7 @@ class Tablerate extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected $_coreConfig;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -118,7 +118,7 @@ class Tablerate extends \Magento\Framework\Model\Resource\Db\AbstractDb
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\OfflineShipping\Model\Carrier\Tablerate $carrierTablerate
@@ -128,7 +128,7 @@ class Tablerate extends \Magento\Framework\Model\Resource\Db\AbstractDb
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\OfflineShipping\Model\Carrier\Tablerate $carrierTablerate,
@@ -316,7 +316,7 @@ class Tablerate extends \Magento\Framework\Model\Resource\Db\AbstractDb
         } catch (\Exception $e) {
             $adapter->rollback();
             $stream->close();
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             throw new \Magento\Framework\Model\Exception(__('Something went wrong while importing table rates.'));
         }
 
diff --git a/app/code/Magento/OfflineShipping/composer.json b/app/code/Magento/OfflineShipping/composer.json
index b48ea50cc45fcb4ed8d8e2290e5575d15ae8f513..013eee21a918d1383bbc17a29eee3624ae148808 100644
--- a/app/code/Magento/OfflineShipping/composer.json
+++ b/app/code/Magento/OfflineShipping/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-sales-rule": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-sales-rule": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/PageCache/composer.json b/app/code/Magento/PageCache/composer.json
index d52cd8ccee9e4ab8d226b86f31c2b0a6bb7893f9..1fa0f7dbb248606b5b558c908aafbff0e6b57769 100644
--- a/app/code/Magento/PageCache/composer.json
+++ b/app/code/Magento/PageCache/composer.json
@@ -3,13 +3,13 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Payment/Model/Method/AbstractMethod.php b/app/code/Magento/Payment/Model/Method/AbstractMethod.php
index 993666627b4ea931f3692fd596a06825617380d9..7f20e76e347c2f68f2c20d37711d84bf6efbd230 100644
--- a/app/code/Magento/Payment/Model/Method/AbstractMethod.php
+++ b/app/code/Magento/Payment/Model/Method/AbstractMethod.php
@@ -70,6 +70,13 @@ abstract class AbstractMethod extends \Magento\Framework\Object implements Metho
      */
     protected $_isGateway = false;
 
+    /**
+     * Payment Method feature
+     *
+     * @var bool
+     */
+    protected $_isOffline = false;
+
     /**
      * Payment Method feature
      *
@@ -197,33 +204,29 @@ abstract class AbstractMethod extends \Magento\Framework\Object implements Metho
     protected $_eventManager;
 
     /**
-     * Log adapter factory
-     *
-     * @var \Magento\Framework\Logger\AdapterFactory
+     * @var \Psr\Log\LoggerInterface
      */
-    protected $_logAdapterFactory;
+    protected $logger;
 
     /**
-     * Construct
-     *
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Payment\Helper\Data $paymentData
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param array $data
      */
     public function __construct(
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Payment\Helper\Data $paymentData,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         array $data = []
     ) {
         parent::__construct($data);
+        $this->logger = $logger;
         $this->_eventManager = $eventManager;
         $this->_paymentData = $paymentData;
         $this->_scopeConfig = $scopeConfig;
-        $this->_logAdapterFactory = $logAdapterFactory;
     }
 
     /**
@@ -370,6 +373,16 @@ abstract class AbstractMethod extends \Magento\Framework\Object implements Metho
         return $this->_isGateway;
     }
 
+    /**
+     * Retrieve payment method online/offline flag
+     *
+     * @return bool
+     */
+    public function isOffline()
+    {
+        return $this->_isOffline;
+    }
+
     /**
      * Flag if we need to run payment initialize while order place
      *
@@ -773,13 +786,7 @@ abstract class AbstractMethod extends \Magento\Framework\Object implements Metho
     protected function _debug($debugData)
     {
         if ($this->getDebugFlag()) {
-            $this->_logAdapterFactory->create(
-                ['fileName' => 'payment_' . $this->getCode() . '.log']
-            )->setFilterDataKeys(
-                $this->_debugReplacePrivateDataKeys
-            )->log(
-                $debugData
-            );
+            $this->logger->debug($debugData);
         }
     }
 
diff --git a/app/code/Magento/Payment/Model/Method/Cc.php b/app/code/Magento/Payment/Model/Method/Cc.php
index 457911b28ea2dc90fdf0bf1eb04f36f7e963ed51..d7383e31db1168005ad8286d553b7e23656e00bd 100644
--- a/app/code/Magento/Payment/Model/Method/Cc.php
+++ b/app/code/Magento/Payment/Model/Method/Cc.php
@@ -38,19 +38,11 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_centinelService;
 
-    /**
-     * Construct
-     *
-     * @var \Magento\Framework\Logger
-     */
-    protected $_logger;
-
     /**
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Payment\Helper\Data $paymentData
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Module\ModuleListInterface $moduleList
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Centinel\Model\Service $centinelService
@@ -60,16 +52,14 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Payment\Helper\Data $paymentData,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Module\ModuleListInterface $moduleList,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Centinel\Model\Service $centinelService,
         array $data = []
     ) {
-        parent::__construct($eventManager, $paymentData, $scopeConfig, $logAdapterFactory, $data);
+        parent::__construct($eventManager, $paymentData, $scopeConfig, $logger, $data);
         $this->_moduleList = $moduleList;
-        $this->_logger = $logger;
         $this->_localeDate = $localeDate;
         $this->_centinelService = $centinelService;
     }
diff --git a/app/code/Magento/Payment/Model/Method/Free.php b/app/code/Magento/Payment/Model/Method/Free.php
index e5bf9c1ba6e1d12487da9d9f930b2ebf6660b970..7463a08bcd5ddb5ae7a065ff16f99b94843bde2b 100644
--- a/app/code/Magento/Payment/Model/Method/Free.php
+++ b/app/code/Magento/Payment/Model/Method/Free.php
@@ -43,7 +43,7 @@ class Free extends \Magento\Payment\Model\Method\AbstractMethod
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Payment\Helper\Data $paymentData
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param PriceCurrencyInterface $priceCurrency
      * @param array $data
      */
@@ -51,11 +51,11 @@ class Free extends \Magento\Payment\Model\Method\AbstractMethod
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Payment\Helper\Data $paymentData,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         PriceCurrencyInterface $priceCurrency,
         array $data = []
     ) {
-        parent::__construct($eventManager, $paymentData, $scopeConfig, $logAdapterFactory, $data);
+        parent::__construct($eventManager, $paymentData, $scopeConfig, $logger, $data);
         $this->priceCurrency = $priceCurrency;
     }
 
diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json
index 65ad4e7e09d884bb06a75846d0e162ae57b0342a..bda90a3cbc12ed22281217e0daf6cfe5b0f87dd0 100644
--- a/app/code/Magento/Payment/composer.json
+++ b/app/code/Magento/Payment/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-centinel": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-centinel": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Persistent/Block/Header/Additional.php b/app/code/Magento/Persistent/Block/Header/Additional.php
index 298052731e37a41d9aebf3e266ddc9cf6bb38b49..4b7f83d2e233582f4b890ea4f41e181224ccad96 100644
--- a/app/code/Magento/Persistent/Block/Header/Additional.php
+++ b/app/code/Magento/Persistent/Block/Header/Additional.php
@@ -44,6 +44,7 @@ class Additional extends \Magento\Framework\View\Element\Html\Link
         \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
         array $data = []
     ) {
+        $this->isScopePrivate = true;
         $this->_customerViewHelper = $customerViewHelper;
         $this->_persistentSessionHelper = $persistentSessionHelper;
         $this->customerRepository = $customerRepository;
@@ -68,12 +69,16 @@ class Additional extends \Magento\Framework\View\Element\Html\Link
      */
     protected function _toHtml()
     {
-        $persistentName = $this->_escaper->escapeHtml(
-            $this->_customerViewHelper->getCustomerName(
-                $this->customerRepository->getById($this->_persistentSessionHelper->getSession()->getCustomerId())
-            )
-        );
-        return '<span><a ' . $this->getLinkAttributes() . ' >' . $this->escapeHtml(__('(Not %1?)', $persistentName))
-        . '</a></span>';
+        if ($this->_persistentSessionHelper->getSession()->getCustomerId()) {
+            $persistentName = $this->escapeHtml(
+                $this->_customerViewHelper->getCustomerName(
+                    $this->customerRepository->getById($this->_persistentSessionHelper->getSession()->getCustomerId())
+                )
+            );
+            return '<span><a ' . $this->getLinkAttributes() . ' >' . __('(Not %1?)', $persistentName)
+            . '</a></span>';
+        }
+
+        return '';
     }
 }
diff --git a/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..46bf6df52128910be28b0609f07219113b827492
--- /dev/null
+++ b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Persistent\Model\Layout;
+
+/**
+ * Class DepersonalizePlugin
+ */
+class DepersonalizePlugin
+{
+    /**
+     * @var \Magento\Persistent\Model\Session
+     */
+    protected $persistentSession;
+
+    /**
+     * @var \Magento\Framework\App\RequestInterface
+     */
+    protected $request;
+
+    /**
+     * @var \Magento\Framework\Module\Manager
+     */
+    protected $moduleManager;
+
+    /**
+     * @var \Magento\PageCache\Model\Config
+     */
+    protected $cacheConfig;
+
+    /**
+     * Constructor
+     *
+     * @param \Magento\Persistent\Model\Session $persistentSession
+     * @param \Magento\Framework\App\RequestInterface $request
+     * @param \Magento\Framework\Module\Manager $moduleManager
+     * @param \Magento\PageCache\Model\Config $cacheConfig
+     */
+    public function __construct(
+        \Magento\Persistent\Model\Session $persistentSession,
+        \Magento\Framework\App\RequestInterface $request,
+        \Magento\Framework\Module\Manager $moduleManager,
+        \Magento\PageCache\Model\Config $cacheConfig
+    ) {
+        $this->persistentSession = $persistentSession;
+        $this->request = $request;
+        $this->moduleManager = $moduleManager;
+        $this->cacheConfig = $cacheConfig;
+    }
+
+    /**
+     * After generate Xml
+     *
+     * @param \Magento\Framework\View\LayoutInterface $subject
+     * @param \Magento\Framework\View\LayoutInterface $result
+     * @return \Magento\Framework\View\LayoutInterface
+     */
+    public function afterGenerateXml(
+        \Magento\Framework\View\LayoutInterface $subject,
+        \Magento\Framework\View\LayoutInterface $result
+    ) {
+        if ($this->moduleManager->isEnabled('Magento_PageCache')
+            && $this->cacheConfig->isEnabled()
+            && !$this->request->isAjax()
+            && $subject->isCacheable()
+        ) {
+            $this->persistentSession->setCustomerId(null);
+        }
+
+        return $result;
+    }
+}
diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json
index f875228c958126bafe01cfa9cfdf4569009e0ea3..e9dfbcdca9f4391893cdc5f6cd39d565678d7781 100644
--- a/app/code/Magento/Persistent/composer.json
+++ b/app/code/Magento/Persistent/composer.json
@@ -3,17 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-cron": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-cron": "0.42.0-beta2",
+        "magento/module-page-cache": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Persistent/etc/frontend/di.xml b/app/code/Magento/Persistent/etc/frontend/di.xml
index 08f489c24699059cb7dc67e01d60f1dac3bd7276..d35e4c3dc204c404b59100908e77862ad3f0ef68 100644
--- a/app/code/Magento/Persistent/etc/frontend/di.xml
+++ b/app/code/Magento/Persistent/etc/frontend/di.xml
@@ -12,4 +12,10 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\View\Layout">
+        <plugin name="persistent-session-depersonalize"
+                type="Magento\Persistent\Model\Layout\DepersonalizePlugin"
+                sortOrder="10"
+        />
+    </type>
 </config>
diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml
index 0a201d7d4ef6e18d49d03945c7e64f55e31288c9..c71ae0efdf48609f9f666542e7b7584fbb3356c5 100644
--- a/app/code/Magento/Persistent/etc/module.xml
+++ b/app/code/Magento/Persistent/etc/module.xml
@@ -8,6 +8,7 @@
     <module name="Magento_Persistent" schema_version="2.0.0">
         <sequence>
             <module name="Magento_Checkout"/>
+            <module name="Magento_PageCache"/>
         </sequence>
     </module>
 </config>
diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json
index 5779c042646080343a4c31301505bde23cfb1df4..ce27de2532c3e7328e648155e34bf190491de40e 100644
--- a/app/code/Magento/ProductAlert/composer.json
+++ b/app/code/Magento/ProductAlert/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Product/Viewed.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Product/Viewed.php
index 00d5e13925e95928fe018ba1f23784ea9fab9fe5..18e7b255e42388be0d491ae9364929c0c814e5e2 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Product/Viewed.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Product/Viewed.php
@@ -49,7 +49,7 @@ class Viewed extends \Magento\Reports\Controller\Adminhtml\Report\Product
             $this->messageManager->addError(
                 __('An error occurred while showing the product views report. Please review the log and try again.')
             );
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('reports/*/viewed/');
             return;
         }
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshLifetime.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshLifetime.php
index 56ca83847b4b662efa53df013ae9a381ed4302b2..956d727041cb81bd6f01998fdb1b536858e1e2d6 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshLifetime.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshLifetime.php
@@ -25,7 +25,7 @@ class RefreshLifetime extends \Magento\Reports\Controller\Adminhtml\Report\Stati
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t refresh lifetime statistics.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
 
         if ($this->_getSession()->isFirstPageAfterLogin()) {
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshRecent.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshRecent.php
index c66170a2e787d12c366c405da51563443420843d..dd6cf080fa7560515e829314fd1b24157ebdedd5 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshRecent.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Statistics/RefreshRecent.php
@@ -28,7 +28,7 @@ class RefreshRecent extends \Magento\Reports\Controller\Adminhtml\Report\Statist
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t refresh recent statistics.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
 
         if ($this->_getSession()->isFirstPageAfterLogin()) {
diff --git a/app/code/Magento/Reports/Model/Resource/Customer/Collection.php b/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
index bf5a1d3c700a0ce830cf9b4b4f652e4c82f8109a..12bf75598b5ce03613ddf542ab597cc2608189ae 100644
--- a/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Customer/Collection.php
@@ -67,7 +67,7 @@ class Collection extends \Magento\Customer\Model\Resource\Customer\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -85,7 +85,7 @@ class Collection extends \Magento\Customer\Model\Resource\Customer\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Reports/Model/Resource/Order/Collection.php b/app/code/Magento/Reports/Model/Resource/Order/Collection.php
index d5fbb0d48a288dcf2923b2bb97cf5d37927afa5e..5e90b28e091f91435c6c8191e095de26ed664541 100644
--- a/app/code/Magento/Reports/Model/Resource/Order/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Order/Collection.php
@@ -56,7 +56,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\DB\Helper $coreResourceHelper
@@ -72,7 +72,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\DB\Helper $coreResourceHelper,
diff --git a/app/code/Magento/Reports/Model/Resource/Product/Collection.php b/app/code/Magento/Reports/Model/Resource/Product/Collection.php
index 04c689b3eb98a8929773043674aad1d8285444a7..28ad32d28ed42b4d9cf85cba759f019529edc7a8 100644
--- a/app/code/Magento/Reports/Model/Resource/Product/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Product/Collection.php
@@ -54,7 +54,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -81,7 +81,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Reports/Model/Resource/Product/Index/Collection/AbstractCollection.php b/app/code/Magento/Reports/Model/Resource/Product/Index/Collection/AbstractCollection.php
index 5e3234b2262125a59fd8cd83876cbccd94aa4ae6..6a980688534b0193bc37a14a75e5ba9b99af2916 100644
--- a/app/code/Magento/Reports/Model/Resource/Product/Index/Collection/AbstractCollection.php
+++ b/app/code/Magento/Reports/Model/Resource/Product/Index/Collection/AbstractCollection.php
@@ -26,7 +26,7 @@ abstract class AbstractCollection extends \Magento\Catalog\Model\Resource\Produc
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -51,7 +51,7 @@ abstract class AbstractCollection extends \Magento\Catalog\Model\Resource\Produc
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Reports/Model/Resource/Product/Lowstock/Collection.php b/app/code/Magento/Reports/Model/Resource/Product/Lowstock/Collection.php
index 6e6251cad6c8b0bedfaad479017ce950911ef04c..c6e28286319ba8f1efd8ac45b823d244031c4b6f 100644
--- a/app/code/Magento/Reports/Model/Resource/Product/Lowstock/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Product/Lowstock/Collection.php
@@ -43,7 +43,7 @@ class Collection extends \Magento\Reports\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -73,7 +73,7 @@ class Collection extends \Magento\Reports\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Reports/Model/Resource/Quote/Collection.php b/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
index 89c1a3ea0d6d09572aaea5d3b92db780860d84ae..50a0031ab5f117d7c448c1b18aff05a204fdf362 100644
--- a/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Quote/Collection.php
@@ -45,7 +45,7 @@ class Collection extends \Magento\Sales\Model\Resource\Quote\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Catalog\Model\Resource\Product\Collection $productResource
@@ -55,7 +55,7 @@ class Collection extends \Magento\Sales\Model\Resource\Quote\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Catalog\Model\Resource\Product\Collection $productResource,
diff --git a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
index 62b6de167e8b70bf3ae00e8550a8c318487cef9f..8fea5b72d7d088f6857cae95a62c95a6d5ffdf7c 100644
--- a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
+++ b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php
@@ -18,7 +18,7 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr
     protected $_flag = null;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -34,7 +34,7 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -42,7 +42,7 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
@@ -451,7 +451,7 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr
                 $nextPeriod = $tr['time'];
             }
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
 
         return $tzTransitions;
diff --git a/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed.php b/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed.php
index 8224d7952e7543ac21bd2cbb8c49ddfcfbb109aa..0065c5b791cdf2d76f5d0d1af73e23a4afd3cf24 100644
--- a/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed.php
+++ b/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed.php
@@ -39,7 +39,7 @@ class Viewed extends \Magento\Sales\Model\Resource\Report\AbstractReport
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -49,7 +49,7 @@ class Viewed extends \Magento\Sales\Model\Resource\Report\AbstractReport
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed/Collection.php b/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed/Collection.php
index b23f2bbafb1cbeba3b87ac8a412e1902277fa269..7923155007ee7995f81221472893c18f14eb24e8 100644
--- a/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Report/Product/Viewed/Collection.php
@@ -26,7 +26,7 @@ class Collection extends \Magento\Reports\Model\Resource\Report\Collection\Abstr
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -34,7 +34,7 @@ class Collection extends \Magento\Reports\Model\Resource\Report\Collection\Abstr
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Reports/Model/Resource/Review/Customer/Collection.php b/app/code/Magento/Reports/Model/Resource/Review/Customer/Collection.php
index 4d9785f546263814bda5dc25c6dcdcfda47d75c6..6c3e9d99b3e7eba017fc1d6e252d132c0489b512 100644
--- a/app/code/Magento/Reports/Model/Resource/Review/Customer/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Review/Customer/Collection.php
@@ -19,7 +19,7 @@ class Collection extends \Magento\Review\Model\Resource\Review\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Review\Helper\Data $reviewData
@@ -31,7 +31,7 @@ class Collection extends \Magento\Review\Model\Resource\Review\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Review\Helper\Data $reviewData,
diff --git a/app/code/Magento/Reports/Model/Resource/Wishlist/Collection.php b/app/code/Magento/Reports/Model/Resource/Wishlist/Collection.php
index f06e1bcabab3cac47db11b47ed1147c14cc2fa32..c692dc1c0acb6415564316f1febe3cee7112c835 100644
--- a/app/code/Magento/Reports/Model/Resource/Wishlist/Collection.php
+++ b/app/code/Magento/Reports/Model/Resource/Wishlist/Collection.php
@@ -26,7 +26,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerResFactory
@@ -35,7 +35,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerResFactory,
diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json
index 7216114373260dd3b76b4836002ba033e6432122..1784a532b0e7cc595d4d486237b1fd0b7532f0bc 100644
--- a/app/code/Magento/Reports/composer.json
+++ b/app/code/Magento/Reports/composer.json
@@ -3,27 +3,27 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-log": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-review": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-downloadable": "0.42.0-beta1",
-        "magento/module-sales-rule": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-log": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-review": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-downloadable": "0.42.0-beta2",
+        "magento/module-sales-rule": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Reports/i18n/de_DE.csv b/app/code/Magento/Reports/i18n/de_DE.csv
index 2afa2d4426da71b2bb9d16e7ce8c58030a01a160..b2bd8ea9e794c94b53e26c11e1327a4b606c2230 100644
--- a/app/code/Magento/Reports/i18n/de_DE.csv
+++ b/app/code/Magento/Reports/i18n/de_DE.csv
@@ -11,7 +11,7 @@ Subtotal,Zwischensumme
 Discount,Discount
 Action,Aktion
 Total,Gesamtbetrag
-"Add to Cart","Zum Warenkobrn hinzufügen"
+"Add to Cart","Zum Warenkorb hinzufügen"
 Orders,Aufträge
 Bestsellers,Bestseller
 Customer,Kundenname
diff --git a/app/code/Magento/RequireJs/composer.json b/app/code/Magento/RequireJs/composer.json
index e212cc993b3144d584d36b50d3c4615c817520eb..7b1ca1f8af0d8401887972ab284b276ad78c887c 100644
--- a/app/code/Magento/RequireJs/composer.json
+++ b/app/code/Magento/RequireJs/composer.json
@@ -3,11 +3,11 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Review/Controller/Product.php b/app/code/Magento/Review/Controller/Product.php
index 35f6a85f6e8296f879e666c17c0410b0436a6dd4..1bbc2610ff55c1960cc791a575bcaa62fe062572 100644
--- a/app/code/Magento/Review/Controller/Product.php
+++ b/app/code/Magento/Review/Controller/Product.php
@@ -47,7 +47,7 @@ class Product extends \Magento\Framework\App\Action\Action
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -98,7 +98,7 @@ class Product extends \Magento\Framework\App\Action\Action
      * @param \Magento\Framework\Registry $coreRegistry
      * @param \Magento\Customer\Model\Session $customerSession
      * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
      * @param \Magento\Review\Model\ReviewFactory $reviewFactory
      * @param \Magento\Review\Model\RatingFactory $ratingFactory
@@ -112,7 +112,7 @@ class Product extends \Magento\Framework\App\Action\Action
         \Magento\Framework\Registry $coreRegistry,
         \Magento\Customer\Model\Session $customerSession,
         \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
         \Magento\Review\Model\ReviewFactory $reviewFactory,
         \Magento\Review\Model\RatingFactory $ratingFactory,
@@ -195,7 +195,7 @@ class Product extends \Magento\Framework\App\Action\Action
                 ['product' => $product, 'controller_action' => $this]
             );
         } catch (\Magento\Framework\Model\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return false;
         }
 
diff --git a/app/code/Magento/Review/Model/Resource/Rating.php b/app/code/Magento/Review/Model/Resource/Rating.php
index afc92f067d858fa376eeaca682dd7910e755ae76..64ba57293a0439589dd2a25a84dddcba36be9725 100644
--- a/app/code/Magento/Review/Model/Resource/Rating.php
+++ b/app/code/Magento/Review/Model/Resource/Rating.php
@@ -26,13 +26,13 @@ class Rating extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected $moduleManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Module\Manager $moduleManager
      * @param \Magento\Review\Helper\Data $ratingData
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -40,7 +40,7 @@ class Rating extends \Magento\Framework\Model\Resource\Db\AbstractDb
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Module\Manager $moduleManager,
         \Magento\Review\Helper\Data $ratingData,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
@@ -197,7 +197,7 @@ class Rating extends \Magento\Framework\Model\Resource\Db\AbstractDb
                 }
                 $adapter->commit();
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 $adapter->rollBack();
             }
         }
@@ -233,7 +233,7 @@ class Rating extends \Magento\Framework\Model\Resource\Db\AbstractDb
 
                 $adapter->commit();
             } catch (\Exception $e) {
-                $this->_logger->logException($e);
+                $this->_logger->critical($e);
                 $adapter->rollBack();
             }
         }
diff --git a/app/code/Magento/Review/Model/Resource/Rating/Collection.php b/app/code/Magento/Review/Model/Resource/Rating/Collection.php
index 59a4578e2931d6aaa87081fd929c3604867a4e95..290814cf08be1a5eb87399854e7660f61d43939a 100644
--- a/app/code/Magento/Review/Model/Resource/Rating/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Rating/Collection.php
@@ -29,7 +29,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -39,7 +39,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Review/Model/Resource/Rating/Grid/Collection.php b/app/code/Magento/Review/Model/Resource/Rating/Grid/Collection.php
index 69875d13f8592f23355724c79dde99b4042e00b2..57c530f0a0c10d3531106a6189de672237ec89d4 100644
--- a/app/code/Magento/Review/Model/Resource/Rating/Grid/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Rating/Grid/Collection.php
@@ -20,7 +20,7 @@ class Collection extends \Magento\Review\Model\Resource\Rating\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -31,7 +31,7 @@ class Collection extends \Magento\Review\Model\Resource\Rating\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Review/Model/Resource/Rating/Option/Vote/Collection.php b/app/code/Magento/Review/Model/Resource/Rating/Option/Vote/Collection.php
index 02a3d934520ffc0f36f05255225238e44e0aa13a..c106f65892a244979dd8c154496714bad72d1524 100644
--- a/app/code/Magento/Review/Model/Resource/Rating/Option/Vote/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Rating/Option/Vote/Collection.php
@@ -25,7 +25,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -35,7 +35,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Review/Model/Resource/Review/Collection.php b/app/code/Magento/Review/Model/Resource/Review/Collection.php
index 2e2694c0f86144afb52a2f5071a7af2d8cb551bb..7c0e4fb196a42855429dfe08f8605cae8efc64b6 100644
--- a/app/code/Magento/Review/Model/Resource/Review/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Review/Collection.php
@@ -75,7 +75,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Review\Helper\Data $reviewData
@@ -86,7 +86,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Review\Helper\Data $reviewData,
diff --git a/app/code/Magento/Review/Model/Resource/Review/Product/Collection.php b/app/code/Magento/Review/Model/Resource/Review/Product/Collection.php
index ea67d81c0569b551276eb8fc8419030354d6cdc6..e43f85a0fcfe56a5690e6480c15faf3b55319a26 100644
--- a/app/code/Magento/Review/Model/Resource/Review/Product/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Review/Product/Collection.php
@@ -57,7 +57,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Eav\Model\Config $eavConfig
@@ -83,7 +83,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Eav\Model\Config $eavConfig,
diff --git a/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php b/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php
index b4b00c2d252676b38633a7012505b5ed389c1a75..db45d49c4ce6e9dd1186ae981e5a7fceb482caca 100644
--- a/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php
+++ b/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php
@@ -20,13 +20,13 @@ class Collection extends \Magento\Framework\Data\Collection\Db
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\App\Resource $resource
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\App\Resource $resource
     ) {
diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json
index 3a4cc6f7ba6981753aaf05e9afaa429538659cb3..c0aba7261db0a196b74f57b5d311fc2350cd0a12 100644
--- a/app/code/Magento/Review/composer.json
+++ b/app/code/Magento/Review/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-newsletter": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-newsletter": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Review/view/frontend/layout/checkout_cart_configure.xml b/app/code/Magento/Review/view/frontend/layout/checkout_cart_configure.xml
index 94b9ab847723132217f742a18acf43d1fbcf9172..046550a20b83495449fbfd29e7e49c37cdc35cee 100644
--- a/app/code/Magento/Review/view/frontend/layout/checkout_cart_configure.xml
+++ b/app/code/Magento/Review/view/frontend/layout/checkout_cart_configure.xml
@@ -5,6 +5,7 @@
  */
 -->
 <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <update handle="catalog_product_view"/>
     <body>
         <referenceBlock name="reviews.tab">
             <block class="Magento\Review\Block\Form\Configure" name="product.review.form" as="review_form">
diff --git a/app/code/Magento/Review/view/frontend/layout/wishlist_index_configure.xml b/app/code/Magento/Review/view/frontend/layout/wishlist_index_configure.xml
new file mode 100644
index 0000000000000000000000000000000000000000..046550a20b83495449fbfd29e7e49c37cdc35cee
--- /dev/null
+++ b/app/code/Magento/Review/view/frontend/layout/wishlist_index_configure.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
+    <update handle="catalog_product_view"/>
+    <body>
+        <referenceBlock name="reviews.tab">
+            <block class="Magento\Review\Block\Form\Configure" name="product.review.form" as="review_form">
+                <container name="product.review.form.fields.before" as="form_fields_before" label="Review Form Fields Before"/>
+            </block>
+        </referenceBlock>
+    </body>
+</page>
diff --git a/app/code/Magento/Rss/App/Action/Plugin/BackendAuthentication.php b/app/code/Magento/Rss/App/Action/Plugin/BackendAuthentication.php
index 7e8d7dfefe0057f55cfe19aa9eaac7acf7da8280..46bf1c318dc9d35e09980f606df81dd29f103cf6 100644
--- a/app/code/Magento/Rss/App/Action/Plugin/BackendAuthentication.php
+++ b/app/code/Magento/Rss/App/Action/Plugin/BackendAuthentication.php
@@ -22,7 +22,7 @@ class BackendAuthentication extends \Magento\Backend\App\Action\Plugin\Authentic
     protected $httpAuthentication;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -43,7 +43,7 @@ class BackendAuthentication extends \Magento\Backend\App\Action\Plugin\Authentic
      * @param \Magento\Framework\App\ActionFlag $actionFlag
      * @param \Magento\Framework\Message\ManagerInterface $messageManager
      * @param \Magento\Framework\HTTP\Authentication $httpAuthentication
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\AuthorizationInterface $authorization
      * @param array $aclResources
      */
@@ -54,7 +54,7 @@ class BackendAuthentication extends \Magento\Backend\App\Action\Plugin\Authentic
         \Magento\Framework\App\ActionFlag $actionFlag,
         \Magento\Framework\Message\ManagerInterface $messageManager,
         \Magento\Framework\HTTP\Authentication $httpAuthentication,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\AuthorizationInterface $authorization,
         array $aclResources
     ) {
@@ -99,7 +99,7 @@ class BackendAuthentication extends \Magento\Backend\App\Action\Plugin\Authentic
             try {
                 $this->_auth->login($login, $password);
             } catch (\Magento\Backend\Model\Auth\Exception $e) {
-                $this->logger->logException($e);
+                $this->logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Rss/Controller/Feed.php b/app/code/Magento/Rss/Controller/Feed.php
index 889bbd05af316dde3837f3a0764eed8f747a9999..06a19e3c9dad0117bc9de3ddb12f3559eae07f04 100644
--- a/app/code/Magento/Rss/Controller/Feed.php
+++ b/app/code/Magento/Rss/Controller/Feed.php
@@ -25,7 +25,7 @@ class Feed extends \Magento\Framework\App\Action\Action
     protected $httpAuthentication;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -52,7 +52,7 @@ class Feed extends \Magento\Framework\App\Action\Action
      * @param \Magento\Customer\Model\Session $customerSession
      * @param \Magento\Customer\Api\AccountManagementInterface $customerAccountManagement
      * @param \Magento\Framework\HTTP\Authentication $httpAuthentication
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Framework\App\Action\Context $context,
@@ -62,7 +62,7 @@ class Feed extends \Magento\Framework\App\Action\Action
         \Magento\Customer\Model\Session $customerSession,
         \Magento\Customer\Api\AccountManagementInterface $customerAccountManagement,
         \Magento\Framework\HTTP\Authentication $httpAuthentication,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->rssManager = $rssManager;
         $this->scopeConfig = $scopeConfig;
@@ -86,7 +86,7 @@ class Feed extends \Magento\Framework\App\Action\Action
                 $this->customerSession->setCustomerDataAsLoggedIn($customer);
                 $this->customerSession->regenerateId();
             } catch (\Exception $e) {
-                $this->logger->logException($e);
+                $this->logger->critical($e);
             }
         }
 
diff --git a/app/code/Magento/Rss/composer.json b/app/code/Magento/Rss/composer.json
index d3731ff12a16177d3f5acef17a587d36eaff7b4e..55830ff619d63e6cc39fbc61c160adbfe285bf57 100644
--- a/app/code/Magento/Rss/composer.json
+++ b/app/code/Magento/Rss/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
index 9c2987de3a34dc978ab3cf524df4cb1fd2d42ea1..916a1404540f9cc36f91ca68729da4a18983fde1 100644
--- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
+++ b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php
@@ -832,12 +832,17 @@ abstract class AbstractCondition extends \Magento\Framework\Object implements Co
     }
 
     /**
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
-        return $this->validateAttribute($object->getData($this->getAttribute()));
+        if (!$model->hasData($this->getAttribute())) {
+            $model->load($model->getId());
+        }
+        $attributeValue = $model->getData($this->getAttribute());
+
+        return $this->validateAttribute($attributeValue);
     }
 
     /**
diff --git a/app/code/Magento/Rule/Model/Condition/Combine.php b/app/code/Magento/Rule/Model/Condition/Combine.php
index 8e9355a4957b2b026656f4e896a588e3f5f7a49e..45d78849d03861b87eb1701dde8d8156716808ff 100644
--- a/app/code/Magento/Rule/Model/Condition/Combine.php
+++ b/app/code/Magento/Rule/Model/Condition/Combine.php
@@ -12,7 +12,7 @@ class Combine extends AbstractCondition
     protected $_conditionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -215,7 +215,7 @@ class Combine extends AbstractCondition
                     $this->addCondition($condition);
                     $condition->loadArray($conditionArr, $key);
                 } catch (\Exception $e) {
-                    $this->_logger->logException($e);
+                    $this->_logger->critical($e);
                 }
             }
         }
@@ -316,12 +316,12 @@ class Combine extends AbstractCondition
     }
 
     /**
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
-        return $this->_isValid($object);
+        return $this->_isValid($model);
     }
 
     /**
@@ -338,7 +338,7 @@ class Combine extends AbstractCondition
     /**
      * Is entity valid
      *
-     * @param int|\Magento\Framework\Object $entity
+     * @param int|\Magento\Framework\Model\AbstractModel $entity
      * @return bool
      */
     protected function _isValid($entity)
@@ -351,7 +351,7 @@ class Combine extends AbstractCondition
         $true = (bool)$this->getValue();
 
         foreach ($this->getConditions() as $cond) {
-            if ($entity instanceof \Magento\Framework\Object) {
+            if ($entity instanceof \Magento\Framework\Model\AbstractModel) {
                 $validated = $cond->validate($entity);
             } else {
                 $validated = $cond->validateByEntityId($entity);
diff --git a/app/code/Magento/Rule/Model/Condition/Context.php b/app/code/Magento/Rule/Model/Condition/Context.php
index 5c7a32fb71296411125516b24591589636f8d180..58ef010e230786ca707b31e0d599144751b61401 100644
--- a/app/code/Magento/Rule/Model/Condition/Context.php
+++ b/app/code/Magento/Rule/Model/Condition/Context.php
@@ -32,7 +32,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     protected $_conditionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -41,14 +41,14 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Framework\View\LayoutInterface $layout
      * @param \Magento\Rule\Model\ConditionFactory $conditionFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Framework\View\LayoutInterface $layout,
         \Magento\Rule\Model\ConditionFactory $conditionFactory,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->_assetRepo = $assetRepo;
         $this->_localeDate = $localeDate;
@@ -90,7 +90,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     }
 
     /**
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
index 00034cf90ae766066f4035d3102829de1ac8f8cd..f0d4de7d40fb932111e73fe13d855b55a97f96b3 100644
--- a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
+++ b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
@@ -523,50 +523,50 @@ abstract class AbstractProduct extends \Magento\Rule\Model\Condition\AbstractCon
     /**
      * Validate product attribute value for condition
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
         $attrCode = $this->getAttribute();
 
         if ('category_ids' == $attrCode) {
-            return $this->validateAttribute($object->getAvailableInCategories());
-        } elseif (!isset($this->_entityAttributeValues[$object->getId()])) {
-            if (!$object->getResource()) {
+            return $this->validateAttribute($model->getAvailableInCategories());
+        } elseif (!isset($this->_entityAttributeValues[$model->getId()])) {
+            if (!$model->getResource()) {
                 return false;
             }
-            $attr = $object->getResource()->getAttribute($attrCode);
+            $attr = $model->getResource()->getAttribute($attrCode);
 
             if ($attr && $attr->getBackendType() == 'datetime' && !is_int($this->getValue())) {
                 $this->setValue(strtotime($this->getValue()));
-                $value = strtotime($object->getData($attrCode));
+                $value = strtotime($model->getData($attrCode));
                 return $this->validateAttribute($value);
             }
 
             if ($attr && $attr->getFrontendInput() == 'multiselect') {
-                $value = $object->getData($attrCode);
+                $value = $model->getData($attrCode);
                 $value = strlen($value) ? explode(',', $value) : [];
                 return $this->validateAttribute($value);
             }
 
-            return parent::validate($object);
+            return parent::validate($model);
         } else {
             $result = false;
             // any valid value will set it to TRUE
             // remember old attribute state
-            $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null;
+            $oldAttrValue = $model->hasData($attrCode) ? $model->getData($attrCode) : null;
 
-            foreach ($this->_entityAttributeValues[$object->getId()] as $value) {
-                $attr = $object->getResource()->getAttribute($attrCode);
+            foreach ($this->_entityAttributeValues[$model->getId()] as $value) {
+                $attr = $model->getResource()->getAttribute($attrCode);
                 if ($attr && $attr->getBackendType() == 'datetime') {
                     $value = strtotime($value);
                 } elseif ($attr && $attr->getFrontendInput() == 'multiselect') {
                     $value = strlen($value) ? explode(',', $value) : [];
                 }
 
-                $object->setData($attrCode, $value);
-                $result |= parent::validate($object);
+                $model->setData($attrCode, $value);
+                $result |= parent::validate($model);
 
                 if ($result) {
                     break;
@@ -574,9 +574,9 @@ abstract class AbstractProduct extends \Magento\Rule\Model\Condition\AbstractCon
             }
 
             if (is_null($oldAttrValue)) {
-                $object->unsetData($attrCode);
+                $model->unsetData($attrCode);
             } else {
-                $object->setData($attrCode, $oldAttrValue);
+                $model->setData($attrCode, $oldAttrValue);
             }
 
             return (bool)$result;
diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json
index 523a353b858023a6e9b100437cfc8c552cb653dd..cabe83db1fee9aa40278f507403483fe68c9143c 100644
--- a/app/code/Magento/Rule/composer.json
+++ b/app/code/Magento/Rule/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php
index 7ca3943d4ec36651c90e562c822d8ce89cf0e095..6391503155d4c02d43eff26a83adced789a43b33 100644
--- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php
+++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php
@@ -47,18 +47,4 @@ class Comment extends \Magento\Sales\Block\Adminhtml\Order\Create\AbstractCreate
     {
         return $this->escapeHtml($this->getQuote()->getCustomerNote());
     }
-
-    /**
-     * Get note notification
-     *
-     * @return bool
-     */
-    public function getNoteNotify()
-    {
-        $notify = $this->getQuote()->getCustomerNoteNotify();
-        if (is_null($notify) || $notify) {
-            return true;
-        }
-        return false;
-    }
 }
diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php
index 833932ae64b85f88d583d7ba710442b0b56bc210..dedf8478a6d14ebfd4eedf955608376d9d195d92 100644
--- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php
+++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php
@@ -181,4 +181,18 @@ class Totals extends \Magento\Sales\Block\Adminhtml\Order\Create\AbstractCreate
     {
         return $this->_salesData->canSendNewOrderConfirmationEmail($this->getQuote()->getStoreId());
     }
+
+    /**
+     * Get note notification
+     *
+     * @return bool
+     */
+    public function getNoteNotify()
+    {
+        $notify = $this->getQuote()->getCustomerNoteNotify();
+        if (is_null($notify) || $notify) {
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php
index c807707f19da411d1cb623e558fa97688f9a13c9..a39f367057dc0497aa91b5777064f96f51853a6b 100644
--- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php
+++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php
@@ -17,20 +17,40 @@ class Transactions extends \Magento\Framework\View\Element\Text\ListText impleme
      */
     protected $_authorization;
 
+    /**
+     * Core registry
+     *
+     * @var \Magento\Framework\Registry
+     */
+    protected $_coreRegistry = null;
+
     /**
      * @param \Magento\Framework\View\Element\Context $context
      * @param \Magento\Framework\AuthorizationInterface $authorization
+     * @param \Magento\Framework\Registry $registry
      * @param array $data
      */
     public function __construct(
         \Magento\Framework\View\Element\Context $context,
         \Magento\Framework\AuthorizationInterface $authorization,
+        \Magento\Framework\Registry $registry,
         array $data = []
     ) {
         $this->_authorization = $authorization;
+        $this->_coreRegistry = $registry;
         parent::__construct($context, $data);
     }
 
+    /**
+     * Retrieve order model instance
+     *
+     * @return \Magento\Sales\Model\Order
+     */
+    public function getOrder()
+    {
+        return $this->_coreRegistry->registry('current_order');
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -52,7 +72,7 @@ class Transactions extends \Magento\Framework\View\Element\Text\ListText impleme
      */
     public function canShowTab()
     {
-        return true;
+        return !$this->getOrder()->getPayment()->getMethodInstance()->isOffline();
     }
 
     /**
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php
index 0218e05f6793085849d8395c6f38e8268e6e87c0..94b9f269119ec2fc84bccdfa805dbbfb93a785a1 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php
@@ -24,7 +24,7 @@ class Cancel extends \Magento\Sales\Controller\Adminhtml\Order
                 $this->messageManager->addError($e->getMessage());
             } catch (\Exception $e) {
                 $this->messageManager->addError(__('You have not canceled the item.'));
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             }
             $this->_redirect('sales/order/view', ['order_id' => $order->getId()]);
         }
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
index c6aea409518e1587d8bf91ffd67017233cee30f3..fd22737d14566efd3e36b2c49d6ef4f5370cdb40 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
@@ -123,7 +123,7 @@ class Save extends \Magento\Backend\App\Action
             $this->messageManager->addError($e->getMessage());
             $this->_getSession()->setFormData($data);
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__('Cannot save the credit memo.'));
         }
         $this->_redirect('sales/*/new', ['_current' => true]);
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php
index 39c33005acb51e81d0d9a85be2466d8b196adde8..4db052f51d7bbd75b1c64fc76ffa2399194a44a2 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php
@@ -29,7 +29,7 @@ class Email extends \Magento\Sales\Controller\Adminhtml\Order
                 $this->messageManager->addError($e->getMessage());
             } catch (\Exception $e) {
                 $this->messageManager->addError(__('We couldn\'t send the email order.'));
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             }
             $this->_redirect('sales/order/view', ['order_id' => $order->getId()]);
         }
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php
index 0d6cd7ddf62244cf3e0fba6b15da3aaf12b9c6fa..24eaeae72801812cc512730fd774670cc1fa1827 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php
@@ -188,14 +188,14 @@ class Save extends \Magento\Backend\App\Action
             try {
                 $this->invoiceCommentSender->send($invoice, !empty($data['send_email']), $comment);
             } catch (\Exception $e) {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->messageManager->addError(__('We can\'t send the invoice email.'));
             }
             if ($shipment) {
                 try {
                     $this->shipmentSender->send($shipment, !empty($data['send_email']));
                 } catch (\Exception $e) {
-                    $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                    $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                     $this->messageManager->addError(__('We can\'t send the shipment.'));
                 }
             }
@@ -206,7 +206,7 @@ class Save extends \Magento\Backend\App\Action
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t save the invoice.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->_redirect('sales/*/new', ['order_id' => $orderId]);
     }
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/ReviewPayment.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/ReviewPayment.php
index 6c7215245cd1607bf354d1f230ab058680dd14b9..b1507b81be3a31d2438f18acc1ece5bd902c3521 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/ReviewPayment.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/ReviewPayment.php
@@ -49,7 +49,7 @@ class ReviewPayment extends \Magento\Sales\Controller\Adminhtml\Order
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We couldn\'t update the payment.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->_redirect('sales/order/view', ['order_id' => $order->getId()]);
     }
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/View.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/View.php
index 20ccd84c08b52bda37e6ebb98a60df5ff0db6187..fc4ed63d9b97625594813c0140da3d0a4f5ef8ae 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/View.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/View.php
@@ -26,7 +26,7 @@ class View extends \Magento\Sales\Controller\Adminhtml\Order
                 $this->_redirect('sales/order/index');
                 return;
             } catch (\Exception $e) {
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->messageManager->addError(__('Exception occurred during order load'));
                 $this->_redirect('sales/order/index');
                 return;
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/VoidPayment.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/VoidPayment.php
index 5a637a1ba4743ec559a6b3a432860930c38902ee..1e30725aa5ea56030b59243876eab53b2b90a918 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/VoidPayment.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/VoidPayment.php
@@ -26,7 +26,7 @@ class VoidPayment extends \Magento\Sales\Controller\Adminhtml\Order
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We couldn\'t void the payment.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->_redirect('sales/*/view', ['order_id' => $order->getId()]);
     }
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php b/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php
index 0377fcf35b61563412667c2d4a630f2293c38148..72bdfbd4073f35ddc840c58aca687293834a47f1 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php
@@ -28,7 +28,7 @@ class Fetch extends \Magento\Sales\Controller\Adminhtml\Transactions
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t update the transaction details.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->_redirect('sales/transactions/view', ['_current' => true]);
     }
diff --git a/app/code/Magento/Sales/Model/AbstractNotifier.php b/app/code/Magento/Sales/Model/AbstractNotifier.php
index b6e8e45610a0f8e5bfcace1ca038d427b2a78e3a..d9c808ee4e66d3283e276c776732c126f097f62d 100644
--- a/app/code/Magento/Sales/Model/AbstractNotifier.php
+++ b/app/code/Magento/Sales/Model/AbstractNotifier.php
@@ -5,7 +5,7 @@
 
 namespace Magento\Sales\Model;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Mail\Exception;
 use Magento\Sales\Model\Order\Email\Sender;
 use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory;
@@ -22,7 +22,7 @@ abstract class AbstractNotifier extends \Magento\Framework\Model\AbstractModel
     protected $historyCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -67,7 +67,7 @@ abstract class AbstractNotifier extends \Magento\Framework\Model\AbstractModel
                 $historyItem->save();
             }
         } catch (Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             return false;
         }
         return true;
diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php
index f027b6b36e92550b29b067912c3d15d5ab342a6e..5d06152dd0b3c2dfc508514df37d03942a9ab86f 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/Create.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php
@@ -86,7 +86,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -200,7 +200,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode
      * @param \Magento\Framework\Registry $coreRegistry
      * @param \Magento\Sales\Model\Config $salesConfig
      * @param \Magento\Backend\Model\Session\Quote $quoteSession
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Object\Copy $objectCopyService
      * @param \Magento\Framework\Message\ManagerInterface $messageManager
      * @param Product\Quote\Initializer $quoteInitializer
@@ -226,7 +226,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode
         \Magento\Framework\Registry $coreRegistry,
         \Magento\Sales\Model\Config $salesConfig,
         \Magento\Backend\Model\Session\Quote $quoteSession,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Object\Copy $objectCopyService,
         \Magento\Framework\Message\ManagerInterface $messageManager,
         Product\Quote\Initializer $quoteInitializer,
@@ -1034,7 +1034,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode
             $this->recollectCart();
             throw $e;
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         $this->recollectCart();
 
diff --git a/app/code/Magento/Sales/Model/AdminOrder/EmailSender.php b/app/code/Magento/Sales/Model/AdminOrder/EmailSender.php
index c0c32f00441f4aced21f5e88b26f18e5249d9dbe..9e283b8d52b0787cd4d1be0170d9842a113ce037 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/EmailSender.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/EmailSender.php
@@ -4,7 +4,7 @@
  */
 namespace Magento\Sales\Model\AdminOrder;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Message\ManagerInterface;
 use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Email\Sender\OrderSender;
@@ -53,7 +53,7 @@ class EmailSender
         try {
             $this->orderSender->send($order);
         } catch (\Magento\Framework\Mail\Exception $exception) {
-            $this->logger->logException($exception);
+            $this->logger->critical($exception);
             $this->messageManager->addWarning(
                 __('You did not email your customer. Please check your email settings.')
             );
diff --git a/app/code/Magento/Sales/Model/Config/Ordered.php b/app/code/Magento/Sales/Model/Config/Ordered.php
index 0da1fc08f1006210634707a022741d2948b8d35c..06640009284956ef69f08bff48a5ae10b2c1d47a 100644
--- a/app/code/Magento/Sales/Model/Config/Ordered.php
+++ b/app/code/Magento/Sales/Model/Config/Ordered.php
@@ -59,7 +59,7 @@ abstract class Ordered extends \Magento\Framework\App\Config\Base
     protected $_configCacheType;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -70,13 +70,13 @@ abstract class Ordered extends \Magento\Framework\App\Config\Base
 
     /**
      * @param \Magento\Framework\App\Cache\Type\Config $configCacheType
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Sales\Model\Config $salesConfig
      * @param \Magento\Framework\Simplexml\Element $sourceData
      */
     public function __construct(
         \Magento\Framework\App\Cache\Type\Config $configCacheType,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Sales\Model\Config $salesConfig,
         $sourceData = null
     ) {
diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php
index 540409a35baf4349c244590c48af12137b0f449a..89e8ca8befbd5570256a568b714e10b62e4595da 100644
--- a/app/code/Magento/Sales/Model/Order.php
+++ b/app/code/Magento/Sales/Model/Order.php
@@ -3389,7 +3389,7 @@ class Order extends AbstractModel implements EntityInterface, ApiOrderInterface
         if ($this->getData(ApiOrderInterface::STATUS_HISTORIES) == null) {
             $this->setData(
                 ApiOrderInterface::STATUS_HISTORIES,
-                $this->getPaymentsCollection()->getItems()
+                $this->getStatusHistoryCollection()->getItems()
             );
         }
         return $this->getData(ApiOrderInterface::STATUS_HISTORIES);
diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoNotifier.php b/app/code/Magento/Sales/Model/Order/CreditmemoNotifier.php
index 97cd87fc60b87321732c9e9e19759f6cf852287b..ad1edd48113e6cab4befd3521ed3da98f7f657f6 100644
--- a/app/code/Magento/Sales/Model/Order/CreditmemoNotifier.php
+++ b/app/code/Magento/Sales/Model/Order/CreditmemoNotifier.php
@@ -5,7 +5,7 @@
 
 namespace Magento\Sales\Model\Order;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender;
 use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory;
 
@@ -21,7 +21,7 @@ class CreditmemoNotifier extends \Magento\Sales\Model\AbstractNotifier
     protected $historyCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
diff --git a/app/code/Magento/Sales/Model/Order/InvoiceNotifier.php b/app/code/Magento/Sales/Model/Order/InvoiceNotifier.php
index d8952c48f476627cd16f5746ede37efd92506dc1..e9c82ce7c7293cc1b4a84dc3c39a12a1cf78e5d0 100644
--- a/app/code/Magento/Sales/Model/Order/InvoiceNotifier.php
+++ b/app/code/Magento/Sales/Model/Order/InvoiceNotifier.php
@@ -5,7 +5,7 @@
 
 namespace Magento\Sales\Model\Order;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
 use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory;
 
@@ -21,7 +21,7 @@ class InvoiceNotifier extends \Magento\Sales\Model\AbstractNotifier
     protected $historyCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
diff --git a/app/code/Magento/Sales/Model/Order/Total/Config/Base.php b/app/code/Magento/Sales/Model/Order/Total/Config/Base.php
index f20acae7fc27f59eb0dfd69262c8db615b2c7988..00c098f071f379f693664888b70d5ad805675959 100644
--- a/app/code/Magento/Sales/Model/Order/Total/Config/Base.php
+++ b/app/code/Magento/Sales/Model/Order/Total/Config/Base.php
@@ -37,14 +37,14 @@ class Base extends \Magento\Sales\Model\Config\Ordered
 
     /**
      * @param \Magento\Framework\App\Cache\Type\Config $configCacheType
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Sales\Model\Config $salesConfig
      * @param \Magento\Sales\Model\Order\TotalFactory $orderTotalFactory
      * @param mixed $sourceData
      */
     public function __construct(
         \Magento\Framework\App\Cache\Type\Config $configCacheType,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Sales\Model\Config $salesConfig,
         \Magento\Sales\Model\Order\TotalFactory $orderTotalFactory,
         $sourceData = null
diff --git a/app/code/Magento/Sales/Model/OrderNotifier.php b/app/code/Magento/Sales/Model/OrderNotifier.php
index 2177000ca1501edeccbfc08b12c29b34b596a846..317a49b0c5d2cc6a3caf186ae7c617518ab6aae9 100644
--- a/app/code/Magento/Sales/Model/OrderNotifier.php
+++ b/app/code/Magento/Sales/Model/OrderNotifier.php
@@ -5,7 +5,7 @@
 
 namespace Magento\Sales\Model;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Sales\Model\Order\Email\Sender\OrderSender;
 use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory;
 
@@ -21,7 +21,7 @@ class OrderNotifier extends \Magento\Sales\Model\AbstractNotifier
     protected $historyCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
diff --git a/app/code/Magento/Sales/Model/Quote/Address/Total/Collector.php b/app/code/Magento/Sales/Model/Quote/Address/Total/Collector.php
index 7458e105508f49e86e7cb108a8c4307826cd2a29..9c711850919a76a9a2f93b92b8f1b8e4ff89c8b6 100644
--- a/app/code/Magento/Sales/Model/Quote/Address/Total/Collector.php
+++ b/app/code/Magento/Sales/Model/Quote/Address/Total/Collector.php
@@ -61,7 +61,7 @@ class Collector extends \Magento\Sales\Model\Config\Ordered
 
     /**
      * @param \Magento\Framework\App\Cache\Type\Config $configCacheType
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Sales\Model\Config $salesConfig
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -71,7 +71,7 @@ class Collector extends \Magento\Sales\Model\Config\Ordered
      */
     public function __construct(
         \Magento\Framework\App\Cache\Type\Config $configCacheType,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Sales\Model\Config $salesConfig,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Collection.php
index 3a2e120ca3b3573d937183702b2dd90de7b5d04c..a27701d5112c846abf4ba7bd7ddb660b4cc6b378 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Collection.php
@@ -35,7 +35,7 @@ class Collection extends AbstractCollection implements OrderSearchResultInterfac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\DB\Helper $coreResourceHelper
@@ -44,7 +44,7 @@ class Collection extends AbstractCollection implements OrderSearchResultInterfac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\DB\Helper $coreResourceHelper,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
index 21e235b812607dfd972a9c380ee69bf434e48deb..2cade1f151f745026a5657402e061988ae6b22ab 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Order/Grid/Collection.php
@@ -18,7 +18,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Creditmemo\Grid\Col
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
@@ -27,7 +27,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Creditmemo\Grid\Col
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Registry $registryManager,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
index b4dc1664e44f58f94cf383fee2489425660d95e7..8f3b2f013182887b0f8629353552c951ecd4c29e 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Orders/Grid/Collection.php
@@ -13,7 +13,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Invoice\Grid\Collec
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
@@ -22,7 +22,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Invoice\Grid\Collec
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Registry $registryManager,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
index 5afc10aacfae73b71ff0b6bdc23d09c6db2a4474..b303628884586f524468493b37018845a3d9c09a 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Payment/Collection.php
@@ -28,7 +28,7 @@ class Collection extends AbstractCollection implements OrderPaymentSearchResultI
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Zend_Db_Adapter_Abstract $connection
@@ -36,7 +36,7 @@ class Collection extends AbstractCollection implements OrderPaymentSearchResultI
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         $connection = null,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
index 56da2f266f1b8e90a30f322ee6ad29d733e794c3..e5a1677943e36df854ae82d7f7b798935ef5d21d 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Order/Grid/Collection.php
@@ -18,7 +18,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Shipment\Grid\Colle
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
@@ -27,7 +27,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Shipment\Grid\Colle
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Registry $registryManager,
diff --git a/app/code/Magento/Sales/Model/Resource/Order/Status.php b/app/code/Magento/Sales/Model/Resource/Order/Status.php
index 34a9b9608b36252fe6c6b326e05495bbc4ab27e5..df6258b3683b0b1e107e6379a77b9c1efc9b81c4 100644
--- a/app/code/Magento/Sales/Model/Resource/Order/Status.php
+++ b/app/code/Magento/Sales/Model/Resource/Order/Status.php
@@ -5,7 +5,7 @@
 namespace Magento\Sales\Model\Resource\Order;
 
 use Magento\Framework\App\Resource;
-use Magento\Framework\Logger as LogWriter;
+use Psr\Log\LoggerInterface as LogWriter;
 use Magento\Framework\Model\Exception;
 
 /**
@@ -30,7 +30,7 @@ class Status extends \Magento\Framework\Model\Resource\Db\AbstractDb
     protected $stateTable;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
diff --git a/app/code/Magento/Sales/Model/Resource/Quote/Address/Rate/Collection.php b/app/code/Magento/Sales/Model/Resource/Quote/Address/Rate/Collection.php
index e88135a1bfa0e9d784ee2e655344f94ee7c25da9..e726f76e37c19ef77826e85e1e3bfd12b6bbac56 100644
--- a/app/code/Magento/Sales/Model/Resource/Quote/Address/Rate/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Quote/Address/Rate/Collection.php
@@ -20,7 +20,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Quote\Address\CarrierFactoryInterface $carrierFactory
@@ -29,7 +29,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Quote\Address\CarrierFactoryInterface $carrierFactory,
diff --git a/app/code/Magento/Sales/Model/Resource/Quote/Item/Collection.php b/app/code/Magento/Sales/Model/Resource/Quote/Item/Collection.php
index 1aa6352b2238b4964b8706dbbb590a793013f539..979e29328651a6c5067b4587a7edff0b2379cb30 100644
--- a/app/code/Magento/Sales/Model/Resource/Quote/Item/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Quote/Item/Collection.php
@@ -40,7 +40,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Quote\Item\Option\CollectionFactory $itemOptionCollectionFactory
@@ -51,7 +51,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Quote\Item\Option\CollectionFactory $itemOptionCollectionFactory,
diff --git a/app/code/Magento/Sales/Model/Resource/Quote/Payment/Collection.php b/app/code/Magento/Sales/Model/Resource/Quote/Payment/Collection.php
index 178e03ab5dbdb0d8e210a036e56ba237a0d0131e..1a3a1f075433f8e727065735792db5ad353f2866 100644
--- a/app/code/Magento/Sales/Model/Resource/Quote/Payment/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Quote/Payment/Collection.php
@@ -11,7 +11,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 {
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Zend_Db_Adapter_Abstract $connection
@@ -19,7 +19,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         $connection = null,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers.php b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers.php
index 9e9cbc9bb7949f9ee8fff9d7dfd7b16de11ecc79..49989878dc42fc596112be51a000f68f46190e12 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers.php
@@ -36,7 +36,7 @@ class Bestsellers extends AbstractReport
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -47,7 +47,7 @@ class Bestsellers extends AbstractReport
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
index 73525e8f13a33274f9111c4cd10ff1bb7a238032..16782bc6898734e65640e4070b9ec5f17abc2093 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Bestsellers/Collection.php
@@ -27,7 +27,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -35,7 +35,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Collection/AbstractCollection.php b/app/code/Magento/Sales/Model/Resource/Report/Collection/AbstractCollection.php
index d6142402445a614e5700286ca99d58eb1cf71a7e..7a8bd502caaaeb67053ee7d9f24bd9d3cfe02a51 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Collection/AbstractCollection.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Collection/AbstractCollection.php
@@ -20,7 +20,7 @@ class AbstractCollection extends \Magento\Reports\Model\Resource\Report\Collecti
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -28,7 +28,7 @@ class AbstractCollection extends \Magento\Reports\Model\Resource\Report\Collecti
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Invoiced.php b/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Invoiced.php
index 73be9036f20f15e3a2ee52e1b53e86ad9b557acf..1f6c851355688a7e5bc91ba27d8c19b331cc6c37 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Invoiced.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Invoiced.php
@@ -13,7 +13,7 @@ class Invoiced extends Order
 {
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -21,7 +21,7 @@ class Invoiced extends Order
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Order.php b/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Order.php
index 600501645c53e5ea45da79377783ef54c2426c6b..f2a9f172b2fa2a2300cd69fa5bc4284f93b6463a 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Order.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Invoiced/Collection/Order.php
@@ -27,7 +27,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -35,7 +35,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Order.php b/app/code/Magento/Sales/Model/Resource/Report/Order.php
index c18cbf90c5e5467ff7be964bb3dcedad655bcb3c..4e8dea3eb1e9dde45bcfba4c46d6b7004e4d641a 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Order.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Order.php
@@ -21,7 +21,7 @@ class Order extends AbstractReport
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -31,7 +31,7 @@ class Order extends AbstractReport
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Order/Collection.php b/app/code/Magento/Sales/Model/Resource/Report/Order/Collection.php
index 4c6afaa58c819fb2524ca4a92b05660e044a638c..61143dda0bd003ed575ed37c7971aef2d68420de 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Order/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Order/Collection.php
@@ -34,7 +34,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -42,7 +42,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Order.php b/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Order.php
index 4c9615483775d92b8b4514e1e5cb91f9327470b5..ff0eb84377c04c9673f43d118b5f48ffcb8fb1c6 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Order.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Order.php
@@ -27,7 +27,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -35,7 +35,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Refunded.php b/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Refunded.php
index 820e18229b6cddbdb678c55e01fe53f712b74043..d79ab374ac25f2e723053d089227767038275e5b 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Refunded.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Refunded/Collection/Refunded.php
@@ -13,7 +13,7 @@ class Refunded extends Order
 {
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -21,7 +21,7 @@ class Refunded extends Order
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Order.php b/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Order.php
index a9b72b30be0e0428f1098c8f5a432c2d45d0a3d9..cedf8781e90693fc91e12b7a5a753560689c6952 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Order.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Order.php
@@ -27,7 +27,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -35,7 +35,7 @@ class Order extends \Magento\Sales\Model\Resource\Report\Collection\AbstractColl
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Shipment.php b/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Shipment.php
index ceaf16cf728ba9b6a1f7fc4aa05ac6aceb12ee10..b2fcd7ac9dc8208bf0eb770ccf0ea92584b5fb80 100644
--- a/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Shipment.php
+++ b/app/code/Magento/Sales/Model/Resource/Report/Shipping/Collection/Shipment.php
@@ -13,7 +13,7 @@ class Shipment extends Order
 {
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -21,7 +21,7 @@ class Shipment extends Order
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Sales/Model/Resource/Sale/Collection.php b/app/code/Magento/Sales/Model/Resource/Sale/Collection.php
index 99d40d4961df1940071cc9e8edbfcc661b4f07be..d0987f3d99d2c4bfc503c7cb62b68eb90002d7fa 100644
--- a/app/code/Magento/Sales/Model/Resource/Sale/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Sale/Collection.php
@@ -8,7 +8,7 @@ use Magento\Core\Model\EntityFactory;
 use Magento\Store\Model\StoreManagerInterface;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 use Magento\Framework\Event\ManagerInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Sales\Model\Resource\Order;
 
 /**
diff --git a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
index 438a0998be99b8bf6ca6878954118918175f6a8a..4f8bb993dbd046202a8f8563d5bd73a1c2028068 100644
--- a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
+++ b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/Collection.php
@@ -16,7 +16,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Payment\Transaction
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Registry $registryManager
@@ -25,7 +25,7 @@ class Collection extends \Magento\Sales\Model\Resource\Order\Payment\Transaction
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Registry $registryManager,
diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json
index a1b36f44f8929af47e37408ec19aeced0642c01d..5220cd715a079bffa3c6645516c5891fae399dc0 100644
--- a/app/code/Magento/Sales/composer.json
+++ b/app/code/Magento/Sales/composer.json
@@ -3,32 +3,32 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-authorization": "0.42.0-beta1",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-sales-rule": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-gift-message": "0.42.0-beta1",
-        "magento/module-reports": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-wishlist": "0.42.0-beta1",
-        "magento/module-email": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-authorization": "0.42.0-beta2",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-sales-rule": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-gift-message": "0.42.0-beta2",
+        "magento/module-reports": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-wishlist": "0.42.0-beta2",
+        "magento/module-email": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sales/i18n/de_DE.csv b/app/code/Magento/Sales/i18n/de_DE.csv
index 6cec0c16a19dcdfc2f2ad2c88fb48fc7fe70b71c..38a17ecbf53862979255598c32f030d117e98342 100644
--- a/app/code/Magento/Sales/i18n/de_DE.csv
+++ b/app/code/Magento/Sales/i18n/de_DE.csv
@@ -33,7 +33,7 @@ Total,Gesamt
 "Move to Wishlist","Auf Wunschzettel schreiben"
 Edit,Bearbeiten
 Item,Objekt
-"Add to Cart","Zum Warenkobrn hinzufügen"
+"Add to Cart","Zum Warenkorb hinzufügen"
 Sku,SKU
 "Order saving error: %1","Order saving error: %1"
 "You created the order.","You created the order."
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml
index 31c3a50031389f1d74a97b7c784763df490d04b3..2e104cccf9ef4051f29cdd9137a4943c6a93fea3 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml
@@ -13,7 +13,7 @@
 <div class="divider"></div>
 <div class="order-totals-bottom">
     <div class="field choice field-append-comments">
-        <input type="checkbox" id="notify_customer" name="order[comment][customer_note_notify]" value="1" <?php if ($this->getNoteNotify()): ?>checked="true"<?php endif; ?>/>
+        <input type="checkbox" id="notify_customer" name="order[comment][customer_note_notify]" value="1"<?php if ($this->getNoteNotify()): ?> checked="checked"<?php endif; ?>/>
         <label for="notify_customer" class="normal"><?php echo __('Append Comments') ?></label>
     </div>
     <?php if ($this->canSendNewOrderConfirmationEmail()): ?>
diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php
index de4dc93a3a8d027f84dd9453e40b19ad50c671d9..cd5fe932c1bfe2ed916eef49e4234dd55d2a30a7 100644
--- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php
+++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php
@@ -29,7 +29,7 @@ class Delete extends \Magento\SalesRule\Controller\Adminhtml\Promo\Quote
                 $this->messageManager->addError(
                     __('An error occurred while deleting the rule. Please review the log and try again.')
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->_redirect('sales_rule/*/edit', ['id' => $this->getRequest()->getParam('id')]);
                 return;
             }
diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Generate.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Generate.php
index e2bc24c960c9a97c62fdaa7e08353988b1f9bdaf..c29d02cc2d3f39a0d733ffb2ab209bf6b77e39c9 100644
--- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Generate.php
+++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Generate.php
@@ -52,7 +52,7 @@ class Generate extends \Magento\SalesRule\Controller\Adminhtml\Promo\Quote
                 $result['error'] = __(
                     'Something went wrong while generating coupons. Please review the log and try again.'
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             }
         }
         $this->getResponse()->representJson(
diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
index 515cfc481f1d206e0d34f2272bbf40316f800956..1aa9ed6cc533d5c60405a2ef2a303d7a573b6bc9 100644
--- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
+++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Save.php
@@ -93,7 +93,7 @@ class Save extends \Magento\SalesRule\Controller\Adminhtml\Promo\Quote
                 $this->messageManager->addError(
                     __('An error occurred while saving the rule data. Please review the log and try again.')
                 );
-                $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                 $this->_objectManager->get('Magento\Backend\Model\Session')->setPageData($data);
                 $this->_redirect('sales_rule/*/edit', ['id' => $this->getRequest()->getParam('rule_id')]);
                 return;
diff --git a/app/code/Magento/SalesRule/Model/Resource/Report/Collection.php b/app/code/Magento/SalesRule/Model/Resource/Report/Collection.php
index 9e0e726e5016667c768bc0ebab42e78d1aa40eb7..8ef7dfc1de56854677f7f43614c8c915a8cc043d 100644
--- a/app/code/Magento/SalesRule/Model/Resource/Report/Collection.php
+++ b/app/code/Magento/SalesRule/Model/Resource/Report/Collection.php
@@ -46,7 +46,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -55,7 +55,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/SalesRule/Model/Resource/Report/Rule.php b/app/code/Magento/SalesRule/Model/Resource/Report/Rule.php
index ad81ce6fd4077244bb55fccc6c9fe12eaea3cb59..43ac17f896e14b1bb73dff57fbc61fcf018dcc65 100644
--- a/app/code/Magento/SalesRule/Model/Resource/Report/Rule.php
+++ b/app/code/Magento/SalesRule/Model/Resource/Report/Rule.php
@@ -23,7 +23,7 @@ class Rule extends \Magento\Reports\Model\Resource\Report\AbstractReport
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -33,7 +33,7 @@ class Rule extends \Magento\Reports\Model\Resource\Report\AbstractReport
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php b/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php
index 9e3ec5c0403365310e91fc63114e51199fb09931..63bd5a0554ec11e0b87c172ad1e8ef0327d2c85d 100644
--- a/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php
+++ b/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php
@@ -94,7 +94,10 @@ class Createdat extends \Magento\Reports\Model\Resource\Report\AbstractReport
                         'base_subtotal_canceled',
                         0
                     ) . ' - ' . $adapter->getIfNullSql(
-                        'ABS(base_discount_amount) - ' . $adapter->getIfNullSql('base_discount_canceled', 0),
+                        'ABS(base_discount_amount) - ABS(' . $adapter->getIfNullSql('base_discount_canceled', 0) . ')',
+                        0
+                    ) . ' + ' . $adapter->getIfNullSql(
+                        'base_tax_amount - ' . $adapter->getIfNullSql('base_tax_canceled', 0),
                         0
                     ) . ')
                         * base_to_global_rate)',
@@ -120,9 +123,12 @@ class Createdat extends \Magento\Reports\Model\Resource\Report\AbstractReport
                         'base_subtotal_refunded',
                         0
                     ) . ' - ' . $adapter->getIfNullSql(
-                        'base_discount_invoiced - ' . $adapter->getIfNullSql('base_discount_refunded', 0),
+                        'ABS(base_discount_invoiced) - ABS(' . $adapter->getIfNullSql('base_discount_refunded', 0) . ')',
                         0
-                    ) . ') * base_to_global_rate)',
+                    ) . ' + ' . $adapter->getIfNullSql(
+                        'base_tax_invoiced - ' . $adapter->getIfNullSql('base_tax_refunded', 0),
+                        0
+                    )   . ') * base_to_global_rate)',
                     0
                 ),
             ];
diff --git a/app/code/Magento/SalesRule/Model/Resource/Rule/Collection.php b/app/code/Magento/SalesRule/Model/Resource/Rule/Collection.php
index b8d8057dd82381d62e3e5841ac0ac5e25c5f90ef..ba0fb345b2692af8d324aa2e70d106bc9d8621c9 100644
--- a/app/code/Magento/SalesRule/Model/Resource/Rule/Collection.php
+++ b/app/code/Magento/SalesRule/Model/Resource/Rule/Collection.php
@@ -36,7 +36,7 @@ class Collection extends \Magento\Rule\Model\Resource\Rule\Collection\AbstractCo
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
@@ -45,7 +45,7 @@ class Collection extends \Magento\Rule\Model\Resource\Rule\Collection\AbstractCo
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\Stdlib\DateTime\DateTime $date,
diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
index 49983011229bbcad73b1b30522e7f2e81090bd93..5589be55402fcc313d92320bb3936a5337f9b846 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php
@@ -160,22 +160,22 @@ class Address extends \Magento\Rule\Model\Condition\AbstractCondition
     /**
      * Validate Address Rule Condition
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
-        $address = $object;
+        $address = $model;
         if (!$address instanceof \Magento\Sales\Model\Quote\Address) {
-            if ($object->getQuote()->isVirtual()) {
-                $address = $object->getQuote()->getBillingAddress();
+            if ($model->getQuote()->isVirtual()) {
+                $address = $model->getQuote()->getBillingAddress();
             } else {
-                $address = $object->getQuote()->getShippingAddress();
+                $address = $model->getQuote()->getShippingAddress();
             }
         }
 
         if ('payment_method' == $this->getAttribute() && !$address->hasPaymentMethod()) {
-            $address->setPaymentMethod($object->getQuote()->getPayment()->getMethod());
+            $address->setPaymentMethod($model->getQuote()->getPayment()->getMethod());
         }
 
         return parent::validate($address);
diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
index 9b614b59ae334bd77f35da6f781db5349da99c44..2f4fcbf7c0af2424f2c645b4357b26171c1f5bea 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
@@ -28,24 +28,24 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
     /**
      * Validate Product Rule Condition
      *
-     * @param \Magento\Framework\Object $object
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
         //@todo reimplement this method when is fixed MAGETWO-5713
         /** @var \Magento\Catalog\Model\Product $product */
-        $product = $object->getProduct();
+        $product = $model->getProduct();
         if (!$product instanceof \Magento\Catalog\Model\Product) {
-            $product = $this->productRepository->getById($object->getProductId());
+            $product = $this->productRepository->getById($model->getProductId());
         }
 
         $product->setQuoteItemQty(
-            $object->getQty()
+            $model->getQty()
         )->setQuoteItemPrice(
-            $object->getPrice() // possible bug: need to use $object->getBasePrice()
+            $model->getPrice() // possible bug: need to use $model->getBasePrice()
         )->setQuoteItemRowTotal(
-            $object->getBaseRowTotal()
+            $model->getBaseRowTotal()
         );
 
         return parent::validate($product);
diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php
index c36ee4671e1d41083c0aa7e05583b44f3430bd09..bea0defa401ebbadb578e1bea86061dc2c1c619d 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php
@@ -52,15 +52,15 @@ class Found extends \Magento\SalesRule\Model\Rule\Condition\Product\Combine
     /**
      * Validate
      *
-     * @param \Magento\Framework\Object $object Quote
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
         $all = $this->getAggregator() === 'all';
         $true = (bool)$this->getValue();
         $found = false;
-        foreach ($object->getAllItems() as $item) {
+        foreach ($model->getAllItems() as $item) {
             $found = $all;
             foreach ($this->getConditions() as $cond) {
                 $validated = $cond->validate($item);
diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php
index 59a5455e96b91b9174874d3b12c84464e387dd4c..08f75032598088f2f081167c7f3b412a0af0d227 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php
@@ -133,17 +133,17 @@ class Subselect extends \Magento\SalesRule\Model\Rule\Condition\Product\Combine
     /**
      * Validate
      *
-     * @param \Magento\Framework\Object $object Quote
+     * @param \Magento\Framework\Model\AbstractModel $model
      * @return bool
      */
-    public function validate(\Magento\Framework\Object $object)
+    public function validate(\Magento\Framework\Model\AbstractModel $model)
     {
         if (!$this->getConditions()) {
             return false;
         }
         $attr = $this->getAttribute();
         $total = 0;
-        foreach ($object->getQuote()->getAllVisibleItems() as $item) {
+        foreach ($model->getQuote()->getAllVisibleItems() as $item) {
             if (parent::validate($item)) {
                 $total += $item->getData($attr);
             }
diff --git a/app/code/Magento/SalesRule/Model/RulesApplier.php b/app/code/Magento/SalesRule/Model/RulesApplier.php
index f7bde08d44e737f81121f7758b645e0e77c869b6..4dace1d8f8df786175108bb19d7b207517dcf5b0 100644
--- a/app/code/Magento/SalesRule/Model/RulesApplier.php
+++ b/app/code/Magento/SalesRule/Model/RulesApplier.php
@@ -59,7 +59,18 @@ class RulesApplier
             }
 
             if (!$skipValidation && !$rule->getActions()->validate($item)) {
-                continue;
+                $childItems = $item->getChildren();
+                $isContinue = true;
+                if (!empty($childItems)) {
+                    foreach ($childItems as $childItem) {
+                        if ($rule->getActions()->validate($childItem)) {
+                            $isContinue = false;
+                        }
+                    }
+                }
+                if ($isContinue) {
+                    continue;
+                }
             }
 
             $this->applyRule($item, $rule, $address, $couponCode);
diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json
index b6346dfd07ba618d86ed6478bf576215523c3776..5017f8928d7bc323eb4b2c10ca1696c65ac4d2f9 100644
--- a/app/code/Magento/SalesRule/composer.json
+++ b/app/code/Magento/SalesRule/composer.json
@@ -3,25 +3,25 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-rule": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/module-reports": "0.42.0-beta1",
-        "magento/module-catalog-rule": "0.42.0-beta1",
-        "magento/module-widget": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-rule": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/module-reports": "0.42.0-beta2",
+        "magento/module-catalog-rule": "0.42.0-beta2",
+        "magento/module-widget": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Search/Model/Resource/Query/Collection.php b/app/code/Magento/Search/Model/Resource/Query/Collection.php
index 07dc2a4f169f1d9cccb41229124e21ed78355fb6..9da9c34b18fb2835e127d9bafc6d0f1ac77bcf81 100644
--- a/app/code/Magento/Search/Model/Resource/Query/Collection.php
+++ b/app/code/Magento/Search/Model/Resource/Query/Collection.php
@@ -35,7 +35,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -45,7 +45,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Search/composer.json b/app/code/Magento/Search/composer.json
index b629eee559fbc9e6cbc459e075b00f01b21e24c4..5043405ad17cf25745b92dc72b0ffffbdf518053 100644
--- a/app/code/Magento/Search/composer.json
+++ b/app/code/Magento/Search/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-reports": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-reports": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sendfriend/composer.json b/app/code/Magento/Sendfriend/composer.json
index 1024ff1f3318de2db25f824529d2218e8f3a34aa..b9fc79a750c35dac0ea6b50d31e4d84a74c37217 100644
--- a/app/code/Magento/Sendfriend/composer.json
+++ b/app/code/Magento/Sendfriend/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabel.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabel.php
index ac12fa4957763d4194055d6d96c7817f533f5b02..5b09369e89f35d2dc5ba0ccc705e1875d4a7adb8 100644
--- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabel.php
+++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabel.php
@@ -64,7 +64,7 @@ class CreateLabel extends \Magento\Backend\App\Action
             $response->setError(true);
             $response->setMessage($e->getMessage());
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $response->setError(true);
             $response->setMessage(__('An error occurred while creating shipping label.'));
         }
diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabel.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabel.php
index f8223143233c74f4b284cf0f4a118eb909389af0..4058d5f0632c340c00f58ea5cf9df0e709cdae4e 100644
--- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabel.php
+++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabel.php
@@ -95,7 +95,7 @@ class PrintLabel extends \Magento\Backend\App\Action
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->messageManager->addError(__('An error occurred while creating shipping label.'));
         }
         $this->_redirect(
diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php
index 075c04dfff05a987e6f6a45266f8ea20433f5878..893cf57a363b12129d7b0b8e31083d1f5a0504d1 100644
--- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php
+++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php
@@ -143,7 +143,7 @@ class Save extends \Magento\Backend\App\Action
                 $this->_redirect('*/*/new', ['order_id' => $this->getRequest()->getParam('order_id')]);
             }
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             if ($isNeedCreateLabel) {
                 $responseAjax->setError(true);
                 $responseAjax->setMessage(__('An error occurred while creating shipping label.'));
diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php
index 4cf071e4acab4fe32213ddf460e0683a1893357e..21a384ed8845e38d1bc8c81e4e9122975f19c7c3 100644
--- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php
+++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php
@@ -86,26 +86,26 @@ abstract class AbstractCarrier extends \Magento\Framework\Object implements Abst
     protected $_rateErrorFactory;
 
     /**
-     * @var \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory
+     * @var \Psr\Log\LoggerInterface
      */
-    protected $_logAdapterFactory;
+    protected $_logger;
 
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param array $data
      */
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         array $data = []
     ) {
         parent::__construct($data);
         $this->_scopeConfig = $scopeConfig;
         $this->_rateErrorFactory = $rateErrorFactory;
-        $this->_logAdapterFactory = $logAdapterFactory;
+        $this->_logger = $logger;
     }
 
     /**
@@ -568,13 +568,7 @@ abstract class AbstractCarrier extends \Magento\Framework\Object implements Abst
     protected function _debug($debugData)
     {
         if ($this->getDebugFlag()) {
-            $this->_logAdapterFactory->create(
-                ['fileName' => 'shipping_' . $this->getCarrierCode() . '.log']
-            )->setFilterDataKeys(
-                $this->_debugReplacePrivateDataKeys
-            )->log(
-                $debugData
-            );
+            $this->_logger->debug($debugData);
         }
     }
 
diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php
index 7337c2a96e1467ae679110a7f3ec70f44c2baf4f..3a8f97aab639ea552ad18aab151d13a809b0c696 100644
--- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php
+++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php
@@ -103,7 +103,7 @@ abstract class AbstractCarrierOnline extends AbstractCarrier
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
@@ -122,7 +122,7 @@ abstract class AbstractCarrierOnline extends AbstractCarrier
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
         \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
@@ -147,7 +147,7 @@ abstract class AbstractCarrierOnline extends AbstractCarrier
         $this->_currencyFactory = $currencyFactory;
         $this->_directoryData = $directoryData;
         $this->stockRegistry = $stockRegistry;
-        parent::__construct($scopeConfig, $rateErrorFactory, $logAdapterFactory, $data);
+        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
     }
 
     /**
diff --git a/app/code/Magento/Shipping/Model/ShipmentNotifier.php b/app/code/Magento/Shipping/Model/ShipmentNotifier.php
index 6f868b0627f59771accf2e66992cee733642ccba..38299cb23fc24fa04a6adf352853552720364710 100644
--- a/app/code/Magento/Shipping/Model/ShipmentNotifier.php
+++ b/app/code/Magento/Shipping/Model/ShipmentNotifier.php
@@ -5,7 +5,7 @@
 
 namespace Magento\Shipping\Model;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Sales\Model\Order\Email\Sender\ShipmentSender;
 use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory;
 
@@ -21,7 +21,7 @@ class ShipmentNotifier extends \Magento\Sales\Model\AbstractNotifier
     protected $historyCollectionFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json
index 7eaa767a4deecab8268bc961cdb3c539852b44ec..36a2294310b4d136c0ccce0ee72db87399b44cc3 100644
--- a/app/code/Magento/Shipping/composer.json
+++ b/app/code/Magento/Shipping/composer.json
@@ -3,27 +3,27 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-contact": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-payment": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-contact": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-payment": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "ext-gd": "*",
         "magento/magento-composer-installer": "*"
     },
     "suggest": {
-        "magento/module-fedex": "0.42.0-beta1",
-        "magento/module-ups": "0.42.0-beta1"
+        "magento/module-fedex": "0.42.0-beta2",
+        "magento/module-ups": "0.42.0-beta2"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json
index e8b37f4c468cbbb91f7eeadf0ebf8fc053e2cbd9..6394181c86c428b7a9b8cadeaa4b910afdae1c54 100644
--- a/app/code/Magento/Sitemap/composer.json
+++ b/app/code/Magento/Sitemap/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog-url-rewrite": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog-url-rewrite": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Store/Model/Resource/Config/Collection/Scoped.php b/app/code/Magento/Store/Model/Resource/Config/Collection/Scoped.php
index 2e416222c87acfd6f59a36bc7128a1072c9994ac..411d7aa62edd2ab7e92975dd256bec645ad0ca0b 100644
--- a/app/code/Magento/Store/Model/Resource/Config/Collection/Scoped.php
+++ b/app/code/Magento/Store/Model/Resource/Config/Collection/Scoped.php
@@ -24,7 +24,7 @@ class Scoped extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCol
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Core\Model\Resource\Config\Data $resource
@@ -34,7 +34,7 @@ class Scoped extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCol
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Core\Model\Resource\Config\Data $resource,
diff --git a/app/code/Magento/Store/Model/StorageFactory.php b/app/code/Magento/Store/Model/StorageFactory.php
index 053a718011087ee8a73e0877efa78073b62b0014..edcf2110824c0a78de8ffaa80274017c16162519 100644
--- a/app/code/Magento/Store/Model/StorageFactory.php
+++ b/app/code/Magento/Store/Model/StorageFactory.php
@@ -30,11 +30,6 @@ class StorageFactory
      */
     protected $_eventManager;
 
-    /**
-     * @var \Magento\Framework\Logger
-     */
-    protected $_log;
-
     /**
      * @var \Magento\Framework\Session\SidResolverInterface
      */
@@ -63,7 +58,6 @@ class StorageFactory
     /**
      * @param \Magento\Framework\ObjectManagerInterface $objectManager
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Framework\Logger $logger
      * @param \Magento\Framework\Session\SidResolverInterface $sidResolver
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Framework\App\Http\Context $httpContext
@@ -75,7 +69,6 @@ class StorageFactory
     public function __construct(
         \Magento\Framework\ObjectManagerInterface $objectManager,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Framework\Logger $logger,
         \Magento\Framework\Session\SidResolverInterface $sidResolver,
         \Magento\Framework\App\State $appState,
         \Magento\Framework\App\Http\Context $httpContext,
@@ -87,7 +80,6 @@ class StorageFactory
         $this->_objectManager = $objectManager;
         $this->_storageClassName = $storageClassName;
         $this->_eventManager = $eventManager;
-        $this->_log = $logger;
         $this->_appState = $appState;
         $this->_sidResolver = $sidResolver;
         $this->_writerModel = $writerModel;
@@ -127,36 +119,6 @@ class StorageFactory
                 $this->_sidResolver->setUseSessionInUrl($useSid);
 
                 $this->_eventManager->dispatch('core_app_init_current_store_after');
-
-                $store = $storage->getStore(true);
-                $logActive = $this->_scopeConfig->isSetFlag(
-                    'dev/log/active',
-                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
-                    $store
-                );
-                if ($logActive || $this->_appState->getMode() === \Magento\Framework\App\State::MODE_DEVELOPER) {
-                    $logFile = $this->_scopeConfig->getValue(
-                        'dev/log/file',
-                        \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
-                        $store
-                    );
-                    $logExceptionFile = $this->_scopeConfig->getValue(
-                        'dev/log/exception_file',
-                        \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
-                        $store
-                    );
-                    $this->_log->unsetLoggers();
-                    $this->_log->addStreamLog(
-                        \Magento\Framework\Logger::LOGGER_SYSTEM,
-                        $logFile,
-                        $this->_writerModel
-                    );
-                    $this->_log->addStreamLog(
-                        \Magento\Framework\Logger::LOGGER_EXCEPTION,
-                        $logExceptionFile,
-                        $this->_writerModel
-                    );
-                }
             }
         }
         return $this->_cache[$className];
diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json
index 80bd98f67ee49922b3252c77ddd75223a49104d5..4ea7b85cd29a9232884d7f8be150ee681b94385e 100644
--- a/app/code/Magento/Store/composer.json
+++ b/app/code/Magento/Store/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
index 41a4916f5928b40190b4b25f864c5402ee1f36d0..20d37aecdcc94dbf2f66d7b2321a436afae74d29 100644
--- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
+++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
@@ -39,7 +39,7 @@ class IgnoreTaxNotification extends \Magento\Tax\Controller\Adminhtml\Tax
         if ($section) {
             try {
                 $path = 'tax/notification/ignore_' . $section;
-                $this->_objectManager->get('\Magento\Core\Model\Resource\Config')
+                $this->_objectManager->get('Magento\Core\Model\Resource\Config')
                     ->saveConfig($path, 1, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0);
             } catch (\Exception $e) {
                 $this->messageManager->addError($e->getMessage());
diff --git a/app/code/Magento/Tax/Model/Resource/Calculation/Rate/Collection.php b/app/code/Magento/Tax/Model/Resource/Calculation/Rate/Collection.php
index e9f427e3b0e6fda6c8251f06f5ef5c98ebf848b6..f70eb49035601ab8b88865f74d4a8980fc8dd71f 100644
--- a/app/code/Magento/Tax/Model/Resource/Calculation/Rate/Collection.php
+++ b/app/code/Magento/Tax/Model/Resource/Calculation/Rate/Collection.php
@@ -22,7 +22,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -31,7 +31,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/Tax/Model/Resource/Report/Collection.php b/app/code/Magento/Tax/Model/Resource/Report/Collection.php
index 7ae32523bcc3a02907e363b1333fcbe5106f5042..6cdfeb5bf15c3e59bd156d17a5d539c0906a1f04 100644
--- a/app/code/Magento/Tax/Model/Resource/Report/Collection.php
+++ b/app/code/Magento/Tax/Model/Resource/Report/Collection.php
@@ -31,7 +31,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Sales\Model\Resource\Report $resource
@@ -39,7 +39,7 @@ class Collection extends \Magento\Sales\Model\Resource\Report\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Sales\Model\Resource\Report $resource,
diff --git a/app/code/Magento/Tax/Model/Resource/Report/Tax.php b/app/code/Magento/Tax/Model/Resource/Report/Tax.php
index f85c89784ca53c5ea017adcf477965ea487d7442..c184dd5bf6e46f4546a1375159d0fcc5b44d1660 100644
--- a/app/code/Magento/Tax/Model/Resource/Report/Tax.php
+++ b/app/code/Magento/Tax/Model/Resource/Report/Tax.php
@@ -22,7 +22,7 @@ class Tax extends \Magento\Reports\Model\Resource\Report\AbstractReport
 
     /**
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Reports\Model\FlagFactory $reportsFlagFactory
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
@@ -32,7 +32,7 @@ class Tax extends \Magento\Reports\Model\Resource\Report\AbstractReport
      */
     public function __construct(
         \Magento\Framework\App\Resource $resource,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Reports\Model\FlagFactory $reportsFlagFactory,
         \Magento\Framework\Stdlib\DateTime $dateTime,
diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php
index 6d97a822c554c2aa5618b2f5a6f086d732263be6..7033763324eb59787c59b05d368bdbd020343fb8 100644
--- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php
+++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php
@@ -5,8 +5,9 @@
 
 namespace Magento\Tax\Model\TaxClass\Source;
 
-use Magento\Tax\Api\Data\TaxClassInterface as TaxClass;
+use Magento\Framework\Exception\StateException;
 use Magento\Tax\Api\TaxClassManagementInterface;
+use Magento\Tax\Api\Data\TaxClassInterface as TaxClass;
 
 /**
  * Customer tax class source model.
@@ -48,33 +49,27 @@ class Customer extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
     /**
      * Retrieve all customer tax classes as an options array.
      *
-     * @param bool $withEmpty
      * @return array
+     * @throws StateException
      */
-    public function getAllOptions($withEmpty = true)
+    public function getAllOptions()
     {
-        if (!$this->_options) {
-            $filter = $this->filterBuilder
-                ->setField(TaxClass::KEY_TYPE)
+        if (empty($this->_options)) {
+            $options = [];
+            $filter = $this->filterBuilder->setField(TaxClass::KEY_TYPE)
                 ->setValue(TaxClassManagementInterface::TYPE_CUSTOMER)
                 ->create();
             $searchCriteria = $this->searchCriteriaBuilder->addFilter([$filter])->create();
             $searchResults = $this->taxClassRepository->getList($searchCriteria);
             foreach ($searchResults->getItems() as $taxClass) {
-                $this->_options[] = [
+                $options[] = [
                     'value' => $taxClass->getClassId(),
                     'label' => $taxClass->getClassName(),
                 ];
             }
+            $this->_options = $options;
         }
 
-        if ($withEmpty) {
-            if (!$this->_options) {
-                return [['value' => '0', 'label' => __('None')]];
-            } else {
-                return array_merge([['value' => '0', 'label' => __('None')]], $this->_options);
-            }
-        }
         return $this->_options;
     }
 }
diff --git a/app/code/Magento/Tax/composer.json b/app/code/Magento/Tax/composer.json
index f064cd1b5adcb280cff3a8c8705d7ef5b77cf460..47a035e7a77e8e0b95872f020e71fdffe688a6eb 100644
--- a/app/code/Magento/Tax/composer.json
+++ b/app/code/Magento/Tax/composer.json
@@ -3,22 +3,22 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-reports": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-reports": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/TaxImportExport/composer.json b/app/code/Magento/TaxImportExport/composer.json
index 6e3cb2bb7fb97e6e674f2b066689df2d0e318cc3..e3af939b3c2cc94c2bfff680324c02f43c7b3cb3 100644
--- a/app/code/Magento/TaxImportExport/composer.json
+++ b/app/code/Magento/TaxImportExport/composer.json
@@ -3,15 +3,15 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Delete.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Delete.php
index 9e3677a44a820425e95012da8b193ebde3b5713c..70ac5381a357524c009bd19429354eecf4168f2b 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Delete.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Delete.php
@@ -35,7 +35,7 @@ class Delete extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('We cannot delete the theme.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         /**
          * @todo Temporary solution. Theme module should not know about the existence of editor module.
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCss.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCss.php
index cfe1325536416e05747812f82828e8c8d8f6fbd3..a36241655f6035d43993f116035a42a665474b78 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCss.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCss.php
@@ -43,7 +43,7 @@ class DownloadCss extends \Magento\Theme\Controller\Adminhtml\System\Design\Them
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('File not found: "%1".', $fileId));
             $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php
index 36dde793b45c4fc2a4966c8d590801df61cdd6d0..38f9b1a5c8095982afe69df87d6164cc15dbac61 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php
@@ -41,7 +41,7 @@ class DownloadCustomCss extends \Magento\Theme\Controller\Adminhtml\System\Desig
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('We cannot find file'));
             $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
     }
 }
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Edit.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Edit.php
index 86d8996180c19969bec44fbadd6f719a7ca4eeed..cc443d1d80b1d92065c5e18de037a7fd25f6c36c 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Edit.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Edit.php
@@ -40,7 +40,7 @@ class Edit extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme
             $this->_redirect('adminhtml/*/');
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We cannot find the theme.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('adminhtml/*/');
         }
     }
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php
index 3eb7a42afd42a461d11177e22a6cc1adc73f278b..2c3965ec8cf2ea017d22c8d0d02c351920e5240c 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php
@@ -69,7 +69,7 @@ class Save extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme
             $redirectBack = true;
         } catch (\Exception $e) {
             $this->messageManager->addError('The theme was not saved');
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $redirectBack ? $this->_redirect(
             'adminhtml/*/edit',
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php
index 6d39f4e303d0cd32b91770b48fdcc6d9a4fc1984..bf7ee434a10958ae7782dae518f40ca3ae93c2d3 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php
@@ -23,7 +23,7 @@ class UploadCss extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme
             $result = ['error' => true, 'message' => $e->getMessage()];
         } catch (\Exception $e) {
             $result = ['error' => true, 'message' => __('We cannot upload the CSS file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php
index efa49e8f6d603be4e579270781fa4d45e1e81c35..6722f35aa165d2ce428632a068146b090a3a15ff 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php
@@ -47,7 +47,7 @@ class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme
             $result = ['error' => true, 'message' => $e->getMessage()];
         } catch (\Exception $e) {
             $result = ['error' => true, 'message' => __('We cannot upload the JS file.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php
index d02e1326cc69718ee6d2f3fcff6042fc45c5774e..cd50539d069a427511be32e6158566086c7d78f4 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php
@@ -22,7 +22,7 @@ class NewFolder extends \Magento\Theme\Controller\Adminhtml\System\Design\Wysiwy
             $result = ['error' => true, 'message' => $e->getMessage()];
         } catch (\Exception $e) {
             $result = ['error' => true, 'message' => __('Sorry, there was an unknown error.')];
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->getResponse()->representJson(
             $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode($result)
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/PreviewImage.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/PreviewImage.php
index 2f42a5585d2e030a12907899d77fd737cb821409..e1bd7a7bec317f4df541ed867f7cdedc274dd591 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/PreviewImage.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/PreviewImage.php
@@ -27,7 +27,7 @@ class PreviewImage extends \Magento\Theme\Controller\Adminhtml\System\Design\Wys
                 DirectoryList::MEDIA
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('core/index/notFound');
         }
     }
diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/TreeJson.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/TreeJson.php
index 1ee9b8980537cb5aba86004bd3bdf25930b26fec..931876210972c1c0dcf7235f765f806284a13c46 100644
--- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/TreeJson.php
+++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/TreeJson.php
@@ -23,7 +23,7 @@ class TreeJson extends \Magento\Theme\Controller\Adminhtml\System\Design\Wysiwyg
                 )
             );
         } catch (\Exception $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->getResponse()->representJson(
                 $this->_objectManager->get('Magento\Core\Helper\Data')->jsonEncode([])
             );
diff --git a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php
index 7b5181a2be052102ace59751e79fb3b038f4b2cc..0dc097aa355a0520b2ec060ff2217f026a61a42e 100644
--- a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php
+++ b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php
@@ -159,7 +159,7 @@ class Storage
             $image->resize(self::THUMBNAIL_WIDTH, self::THUMBNAIL_HEIGHT);
             $image->save($this->mediaWriteDirectory->getAbsolutePath($thumbnailPath));
         } catch (\Magento\Framework\Filesystem\FilesystemException $e) {
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             return false;
         }
 
diff --git a/app/code/Magento/Theme/composer.json b/app/code/Magento/Theme/composer.json
index 7037f3dd26c4f2bdb66f892de9e2ff0f5897aa27..1f40aae7fd2fa3e1ed6a111950c54341895c67ec 100644
--- a/app/code/Magento/Theme/composer.json
+++ b/app/code/Magento/Theme/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-require-js": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-require-js": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "suggest": {
-        "magento/module-translation": "0.42.0-beta1"
+        "magento/module-translation": "0.42.0-beta2"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json
index f2615a6f2fbbf0db2e5a41c37f1b48751ffa071a..58011a9b5fc14f7e4e0cef67e0ad3c02c9dd11d6 100644
--- a/app/code/Magento/Translation/composer.json
+++ b/app/code/Magento/Translation/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json
index f6334f24f4e253fc640f989f4e2b9dd88528fc6e..a718cf1994aa1ce62d691b05ab72da5922d5eb0a 100644
--- a/app/code/Magento/Ui/composer.json
+++ b/app/code/Magento/Ui/composer.json
@@ -3,14 +3,14 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php
index 86a2f8b5bb2f76acecefffaf087cc0d251e0a0c8..8a5ea44b6eff892c3b97852b1df2ca5ef9708f62 100644
--- a/app/code/Magento/Ups/Model/Carrier.php
+++ b/app/code/Magento/Ups/Model/Carrier.php
@@ -105,7 +105,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
     protected $_localeFormat;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -117,7 +117,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
@@ -129,7 +129,6 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
      * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory
      * @param \Magento\Directory\Helper\Data $directoryData
      * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
-     * @param \Magento\Framework\Logger $logger
      * @param \Magento\Framework\Locale\FormatInterface $localeFormat
      * @param Config $configHelper
      * @param array $data
@@ -139,7 +138,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
         \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
@@ -151,18 +150,16 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
         \Magento\Directory\Model\CurrencyFactory $currencyFactory,
         \Magento\Directory\Helper\Data $directoryData,
         \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
-        \Magento\Framework\Logger $logger,
         \Magento\Framework\Locale\FormatInterface $localeFormat,
         Config $configHelper,
         array $data = []
     ) {
-        $this->_logger = $logger;
         $this->_localeFormat = $localeFormat;
         $this->configHelper = $configHelper;
         parent::__construct(
             $scopeConfig,
             $rateErrorFactory,
-            $logAdapterFactory,
+            $logger,
             $xmlElFactory,
             $rateFactory,
             $rateMethodFactory,
@@ -518,7 +515,7 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface
                         $message = __(
                             'Sorry, something went wrong. Please try again or contact us and we\'ll try to help.'
                         );
-                        $this->_logger->log($message . ': ' . $errorTitle);
+                        $this->_logger->debug($message . ': ' . $errorTitle);
                         break;
                     case 6:
                         if (in_array($row[3], $allowedMethods)) {
diff --git a/app/code/Magento/Ups/composer.json b/app/code/Magento/Ups/composer.json
index 1a719011382368262de5b761e00204fef71600ce..70e71fd6080eb60a2481cad8a7064316a4fbc039 100644
--- a/app/code/Magento/Ups/composer.json
+++ b/app/code/Magento/Ups/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/UrlRewrite/Model/Resource/UrlRewriteCollection.php b/app/code/Magento/UrlRewrite/Model/Resource/UrlRewriteCollection.php
index 0e50c89bf2dbc35b588bf66891939657efcf0741..ad3059c13eea4bdc023fe440d20f8c1518310309 100644
--- a/app/code/Magento/UrlRewrite/Model/Resource/UrlRewriteCollection.php
+++ b/app/code/Magento/UrlRewrite/Model/Resource/UrlRewriteCollection.php
@@ -17,7 +17,7 @@ class UrlRewriteCollection extends \Magento\Framework\Model\Resource\Db\Collecti
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -26,7 +26,7 @@ class UrlRewriteCollection extends \Magento\Framework\Model\Resource\Db\Collecti
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json
index 308cde149bc019144992bf5b8d6d16facf77ef57..9944ab44a7311dc2f77479a683ef03375365d63f 100644
--- a/app/code/Magento/UrlRewrite/composer.json
+++ b/app/code/Magento/UrlRewrite/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog-url-rewrite": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-cms-url-rewrite": "0.42.0-beta1",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog-url-rewrite": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-cms-url-rewrite": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/User/Controller/Adminhtml/User/InvalidateToken.php b/app/code/Magento/User/Controller/Adminhtml/User/InvalidateToken.php
index 2fd4c02fffbb593a11905460e3e11f4128388e79..392d87a98f0b7c247fe198aee670b0aba8d2203e 100644
--- a/app/code/Magento/User/Controller/Adminhtml/User/InvalidateToken.php
+++ b/app/code/Magento/User/Controller/Adminhtml/User/InvalidateToken.php
@@ -18,7 +18,7 @@ class InvalidateToken extends \Magento\User\Controller\Adminhtml\User
     {
         if ($userId = $this->getRequest()->getParam('user_id')) {
             /** @var \Magento\Integration\Service\V1\AdminTokenService $tokenService */
-            $tokenService = $this->_objectManager->get('\Magento\Integration\Service\V1\AdminTokenService');
+            $tokenService = $this->_objectManager->get('Magento\Integration\Service\V1\AdminTokenService');
             try {
                 $tokenService->revokeAdminAccessToken($userId);
                 $this->messageManager->addSuccess(__('You have revoked the user\'s tokens.'));
diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Role.php b/app/code/Magento/User/Controller/Adminhtml/User/Role.php
index dcd17cc7111e835448d3072679f108862c4e90e0..0cf36ec618e91ae844de3324b98e0ac1697f821e 100644
--- a/app/code/Magento/User/Controller/Adminhtml/User/Role.php
+++ b/app/code/Magento/User/Controller/Adminhtml/User/Role.php
@@ -43,6 +43,11 @@ class Role extends \Magento\Backend\App\AbstractAction
      */
     protected $_authSession;
 
+    /**
+     * @var \Magento\Framework\Filter\FilterManager
+     */
+    protected $_filterManager;
+
     /**
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Registry $coreRegistry
@@ -50,6 +55,7 @@ class Role extends \Magento\Backend\App\AbstractAction
      * @param \Magento\User\Model\UserFactory $userFactory
      * @param \Magento\Authorization\Model\RulesFactory $rulesFactory
      * @param \Magento\Backend\Model\Auth\Session $authSession
+     * @param \Magento\Framework\Filter\FilterManager $filterManager
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
@@ -57,7 +63,8 @@ class Role extends \Magento\Backend\App\AbstractAction
         \Magento\Authorization\Model\RoleFactory $roleFactory,
         \Magento\User\Model\UserFactory $userFactory,
         \Magento\Authorization\Model\RulesFactory $rulesFactory,
-        \Magento\Backend\Model\Auth\Session $authSession
+        \Magento\Backend\Model\Auth\Session $authSession,
+        \Magento\Framework\Filter\FilterManager $filterManager
     ) {
         parent::__construct($context);
         $this->_coreRegistry = $coreRegistry;
@@ -65,6 +72,7 @@ class Role extends \Magento\Backend\App\AbstractAction
         $this->_userFactory = $userFactory;
         $this->_rulesFactory = $rulesFactory;
         $this->_authSession = $authSession;
+        $this->_filterManager = $filterManager;
     }
 
     /**
diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php b/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php
index 773e39cebef90c872270fe2e6c9763a89ec8bf8e..7041aab2fa6b6f162f95d81fc4ad90bf76455a71 100644
--- a/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php
+++ b/app/code/Magento/User/Controller/Adminhtml/User/Role/SaveRole.php
@@ -78,7 +78,7 @@ class SaveRole extends \Magento\User\Controller\Adminhtml\User\Role
         }
 
         try {
-            $roleName = $this->getRequest()->getParam('rolename', false);
+            $roleName = $this->_filterManager->removeTags($this->getRequest()->getParam('rolename', false));
 
             $role->setName($roleName)
                 ->setPid($this->getRequest()->getParam('parent_id', false))
diff --git a/app/code/Magento/User/composer.json b/app/code/Magento/User/composer.json
index 551e1a3c969f035af2d47d4082fa857ca8d63a3c..aecb0497348818516853b0cd01d6561cb3cee176 100644
--- a/app/code/Magento/User/composer.json
+++ b/app/code/Magento/User/composer.json
@@ -3,18 +3,18 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-authorization": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-integration": "0.42.0-beta1",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-require-js": "0.42.0-beta1",
+        "magento/module-authorization": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-integration": "0.42.0-beta2",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-require-js": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Usps/Model/Carrier.php b/app/code/Magento/Usps/Model/Carrier.php
index d6aebb495fcf7ffdbd180a11d9bf09fd6d9cf72d..7f22a33a79b9a60d707bb934b7e5d4b7d1f7a5b5 100644
--- a/app/code/Magento/Usps/Model/Carrier.php
+++ b/app/code/Magento/Usps/Model/Carrier.php
@@ -107,7 +107,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
-     * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory
      * @param \Magento\Shipping\Model\Rate\ResultFactory $rateFactory
      * @param \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
@@ -129,7 +129,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
         \Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
-        \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
         \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
         \Magento\Sales\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
@@ -152,7 +152,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
         parent::__construct(
             $scopeConfig,
             $rateErrorFactory,
-            $logAdapterFactory,
+            $logger,
             $xmlElFactory,
             $rateFactory,
             $rateMethodFactory,
diff --git a/app/code/Magento/Usps/composer.json b/app/code/Magento/Usps/composer.json
index ced6462e5f0775370a1b5a911c5aba82e61ce863..14d5771423781fd70844873884c4a1b9ebec43b7 100644
--- a/app/code/Magento/Usps/composer.json
+++ b/app/code/Magento/Usps/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-shipping": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-shipping": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "lib-libxml": "*",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Webapi/Controller/ErrorProcessor.php b/app/code/Magento/Webapi/Controller/ErrorProcessor.php
index d810a58015c2f592b8766372dde451318a14b4b5..3e951b285ad67fab5ead489fbe9d1f528f9ccc85 100644
--- a/app/code/Magento/Webapi/Controller/ErrorProcessor.php
+++ b/app/code/Magento/Webapi/Controller/ErrorProcessor.php
@@ -48,7 +48,7 @@ class ErrorProcessor
     protected $_appState;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -67,13 +67,13 @@ class ErrorProcessor
     /**
      * @param \Magento\Core\Helper\Data $helper
      * @param \Magento\Framework\App\State $appState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
      */
     public function __construct(
         \Magento\Core\Helper\Data $helper,
         \Magento\Framework\App\State $appState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem
     ) {
         $this->_coreHelper = $helper;
@@ -134,7 +134,7 @@ class ErrorProcessor
             //if not in Dev mode, make sure the message and code is masked for unanticipated exceptions
             if (!$isDevMode) {
                 /** Log information about actual exception */
-                $reportId = $this->_logException($exception);
+                $reportId = $this->_critical($exception);
                 $message = sprintf(self::INTERNAL_SERVER_ERROR_MSG, $reportId);
                 $code = 0;
             }
@@ -166,7 +166,7 @@ class ErrorProcessor
         if ($this->_appState->getMode() == State::MODE_DEVELOPER || $exception instanceof \Magento\Webapi\Exception) {
             $this->render($exception->getMessage(), $exception->getTraceAsString(), $httpCode);
         } else {
-            $reportId = $this->_logException($exception);
+            $reportId = $this->_critical($exception);
             $this->render(
                 __('Internal Error. Details are available in Magento log file. Report ID: %1', $reportId),
                 'Trace is not available.',
@@ -182,16 +182,16 @@ class ErrorProcessor
      * @param \Exception $exception
      * @return string $reportId
      */
-    protected function _logException(\Exception $exception)
+    protected function _critical(\Exception $exception)
     {
         $exceptionClass = get_class($exception);
         $reportId = uniqid("webapi-");
         $exceptionForLog = new $exceptionClass(
-            /** Trace is added separately by logException. */
+            /** Trace is added separately by critical. */
             "Report ID: {$reportId}; Message: {$exception->getMessage()}",
             $exception->getCode()
         );
-        $this->_logger->logException($exceptionForLog);
+        $this->_logger->critical($exceptionForLog);
         return $reportId;
     }
 
diff --git a/app/code/Magento/Webapi/Model/Config/ClassReflector.php b/app/code/Magento/Webapi/Model/Config/ClassReflector.php
index 51878ad2d0940a8b991908c5e79457ee20a84972..e734ff1ef40ca4bc098f03d9525be3fad63f6cd8 100644
--- a/app/code/Magento/Webapi/Model/Config/ClassReflector.php
+++ b/app/code/Magento/Webapi/Model/Config/ClassReflector.php
@@ -6,6 +6,7 @@ namespace Magento\Webapi\Model\Config;
 
 use Zend\Server\Reflection;
 use Zend\Server\Reflection\ReflectionMethod;
+use Zend\Code\Reflection\MethodReflection;
 
 /**
  * Class reflector.
@@ -84,7 +85,7 @@ class ClassReflector
      */
     public function extractMethodData(ReflectionMethod $method)
     {
-        $methodData = ['documentation' => $method->getDescription(), 'interface' => []];
+        $methodData = ['documentation' => $this->extractMethodDescription($method), 'interface' => []];
         $prototypes = $method->getPrototypes();
         /** Take the fullest interface that also includes optional parameters. */
         /** @var \Zend\Server\Reflection\Prototype $prototype */
@@ -111,4 +112,22 @@ class ClassReflector
 
         return $methodData;
     }
+
+    /**
+     * Retrieve method full documentation description.
+     *
+     * @param ReflectionMethod $method
+     * @return string
+     */
+    protected function extractMethodDescription(ReflectionMethod $method)
+    {
+        $methodReflection = new MethodReflection(
+            $method->getDeclaringClass()->getName(),
+            $method->getName()
+        );
+
+        $docBlock = $methodReflection->getDocBlock();
+
+        return $this->_typeProcessor->getDescription($docBlock);
+    }
 }
diff --git a/app/code/Magento/Webapi/composer.json b/app/code/Magento/Webapi/composer.json
index 78b24f45b4b00340a4864ad368c998cb129577f0..3d520c28732b0d8cbec12c0205256513c63969a7 100644
--- a/app/code/Magento/Webapi/composer.json
+++ b/app/code/Magento/Webapi/composer.json
@@ -3,19 +3,19 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-authorization": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-integration": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-authorization": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-integration": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "suggest": {
-        "magento/module-user": "0.42.0-beta1"
+        "magento/module-user": "0.42.0-beta2"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Weee/composer.json b/app/code/Magento/Weee/composer.json
index adf13a5fe3f93ca03819af4437dbd55e2cce74ea..acee54fa4cca87008487f67f9165a09d4fa59d62 100644
--- a/app/code/Magento/Weee/composer.json
+++ b/app/code/Magento/Weee/composer.json
@@ -3,20 +3,20 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-tax": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-directory": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-eav": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-tax": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-directory": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-eav": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance.php b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance.php
index 6c749bd080fcc9b523a3f53a5463dc4fbd872d1a..447568540595fad9c58122da43cce6b4ae29a29c 100644
--- a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance.php
+++ b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance.php
@@ -23,7 +23,7 @@ class Instance extends \Magento\Backend\App\Action
     protected $_widgetFactory;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -41,7 +41,7 @@ class Instance extends \Magento\Backend\App\Action
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Registry $coreRegistry
      * @param \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Math\Random $mathRandom
      * @param \Magento\Framework\Translate\InlineInterface $translateInline
      */
@@ -49,7 +49,7 @@ class Instance extends \Magento\Backend\App\Action
         \Magento\Backend\App\Action\Context $context,
         \Magento\Framework\Registry $coreRegistry,
         \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Math\Random $mathRandom,
         \Magento\Framework\Translate\InlineInterface $translateInline
     ) {
diff --git a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Save.php b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Save.php
index f756cb5d2b8201acedcc71a9c53dfe3cfb539dc2..d7fd7dd28cca7c03e653a021a628ce494814941c 100644
--- a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Save.php
+++ b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Save.php
@@ -44,7 +44,7 @@ class Save extends \Magento\Widget\Controller\Adminhtml\Widget\Instance
             return;
         } catch (\Exception $exception) {
             $this->messageManager->addError($exception->getMessage());
-            $this->_logger->logException($exception);
+            $this->_logger->critical($exception);
             $this->_redirect('adminhtml/*/edit', ['_current' => true]);
             return;
         }
diff --git a/app/code/Magento/Widget/Model/Template/Filter.php b/app/code/Magento/Widget/Model/Template/Filter.php
index e5c7aa30374b2b8a8969a9c4ffe7c85cbf645dfc..695345a62c8f3d20dbca49ad0fba0b4c8dfe1179 100644
--- a/app/code/Magento/Widget/Model/Template/Filter.php
+++ b/app/code/Magento/Widget/Model/Template/Filter.php
@@ -21,7 +21,7 @@ class Filter extends \Magento\Cms\Model\Template\Filter
 
     /**
      * @param \Magento\Framework\Stdlib\String $string
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -36,7 +36,7 @@ class Filter extends \Magento\Cms\Model\Template\Filter
      */
     public function __construct(
         \Magento\Framework\Stdlib\String $string,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
diff --git a/app/code/Magento/Widget/composer.json b/app/code/Magento/Widget/composer.json
index 6edce51d361e0245d13d9ccacac0106edf48fb60..29a3df73413543ab29957dc658569c70a70c6117 100644
--- a/app/code/Magento/Widget/composer.json
+++ b/app/code/Magento/Widget/composer.json
@@ -3,16 +3,16 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-cms": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-cms": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Wishlist/Controller/Index/Add.php b/app/code/Magento/Wishlist/Controller/Index/Add.php
index 93a5a80497f50a760c1d49811c90a49f1da997e0..7b45de5f6fdac175b8567ddec58d55230502b33d 100644
--- a/app/code/Magento/Wishlist/Controller/Index/Add.php
+++ b/app/code/Magento/Wishlist/Controller/Index/Add.php
@@ -127,7 +127,7 @@ class Add extends Action\Action implements IndexInterface
             );
         } catch (\Exception $e) {
             $this->messageManager->addError(__('An error occurred while adding item to wish list.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
 
         $this->_redirect('*', ['wishlist_id' => $wishlist->getId()]);
diff --git a/app/code/Magento/Wishlist/Controller/Index/Cart.php b/app/code/Magento/Wishlist/Controller/Index/Cart.php
index e0508e6c0e2efa860e0a01bcbdc3407b654e7759..edb018b57b84ec7481d38b773fa7566818e8332c 100644
--- a/app/code/Magento/Wishlist/Controller/Index/Cart.php
+++ b/app/code/Magento/Wishlist/Controller/Index/Cart.php
@@ -21,18 +21,66 @@ class Cart extends Action\Action implements IndexInterface
      */
     protected $quantityProcessor;
 
+    /**
+     * @var \Magento\Wishlist\Model\ItemFactory
+     */
+    protected $itemFactory;
+
+    /**
+     * @var \Magento\Checkout\Model\Cart
+     */
+    protected $cart;
+
+    /**
+     * @var \Magento\Wishlist\Model\Item\OptionFactory
+     */
+    private $optionFactory;
+
+    /**
+     * @var \Magento\Catalog\Helper\Product
+     */
+    protected $productHelper;
+
+    /**
+     * @var \Magento\Framework\Escaper
+     */
+    protected $escaper;
+
+    /**
+     * @var \Magento\Wishlist\Helper\Data
+     */
+    protected $helper;
+
     /**
      * @param Action\Context $context
      * @param \Magento\Wishlist\Controller\WishlistProviderInterface $wishlistProvider
      * @param \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor
+     * @param \Magento\Wishlist\Model\ItemFactory $itemFactory
+     * @param \Magento\Checkout\Model\Cart $cart
+     * @param \Magento\Wishlist\Model\Item\OptionFactory $
+     * @param \Magento\Catalog\Helper\Product $productHelper
+     * @param \Magento\Framework\Escaper $escaper
+     * @param \Magento\Wishlist\Helper\Data $helper
      */
     public function __construct(
         Action\Context $context,
         \Magento\Wishlist\Controller\WishlistProviderInterface $wishlistProvider,
-        \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor
+        \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor,
+        \Magento\Wishlist\Model\ItemFactory $itemFactory,
+        \Magento\Checkout\Model\Cart $cart,
+        \Magento\Wishlist\Model\Item\OptionFactory $optionFactory,
+        \Magento\Catalog\Helper\Product $productHelper,
+        \Magento\Framework\Escaper $escaper,
+        \Magento\Wishlist\Helper\Data $helper
     ) {
         $this->wishlistProvider = $wishlistProvider;
         $this->quantityProcessor = $quantityProcessor;
+        $this->itemFactory = $itemFactory;
+        $this->cart = $cart;
+        $this->optionFactory = $optionFactory;
+        $this->productHelper = $productHelper;
+        $this->escaper = $escaper;
+        $this->helper = $helper;
         parent::__construct($context);
     }
 
@@ -49,7 +97,7 @@ class Cart extends Action\Action implements IndexInterface
         $itemId = (int)$this->getRequest()->getParam('item');
 
         /* @var $item \Magento\Wishlist\Model\Item */
-        $item = $this->_objectManager->create('Magento\Wishlist\Model\Item')->load($itemId);
+        $item = $this->itemFactory->create()->load($itemId);
         if (!$item->getId()) {
             return $this->_redirect('*/*');
         }
@@ -72,70 +120,61 @@ class Cart extends Action\Action implements IndexInterface
             $item->setQty($qty);
         }
 
-        /* @var $session \Magento\Framework\Session\Generic */
-        $session = $this->_objectManager->get('Magento\Wishlist\Model\Session');
-        $cart = $this->_objectManager->get('Magento\Checkout\Model\Cart');
-
         $redirectUrl = $this->_url->getUrl('*/*');
+        $configureUrl = $this->_url->getUrl(
+            '*/*/configure/',
+            [
+                'id' => $item->getId(),
+                'product_id' => $item->getProductId(),
+            ]
+        );
 
         try {
-            $options = $this->_objectManager->create(
-                'Magento\Wishlist\Model\Item\Option'
-            )->getCollection()->addItemFilter(
-                [$itemId]
-            );
+            /** @var \Magento\Wishlist\Model\Resource\Item\Option\Collection $options */
+            $options = $this->optionFactory->create()->getCollection()->addItemFilter([$itemId]);
             $item->setOptions($options->getOptionsByItem($itemId));
 
-            $buyRequest = $this->_objectManager->get(
-                'Magento\Catalog\Helper\Product'
-            )->addParamsToBuyRequest(
+            $buyRequest = $this->productHelper->addParamsToBuyRequest(
                 $this->getRequest()->getParams(),
                 ['current_config' => $item->getBuyRequest()]
             );
 
             $item->mergeBuyRequest($buyRequest);
-            $item->addToCart($cart, true);
-            $cart->save()->getQuote()->collectTotals();
+            $item->addToCart($this->cart, true);
+            $this->cart->save()->getQuote()->collectTotals();
             $wishlist->save();
 
-            if (!$cart->getQuote()->getHasError()) {
+            if (!$this->cart->getQuote()->getHasError()) {
                 $message = __(
                     'You added %1 to your shopping cart.',
-                    $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($item->getProduct()->getName())
+                    $this->escaper->escapeHtml($item->getProduct()->getName())
                 );
                 $this->messageManager->addSuccess($message);
             }
 
-            $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate();
-
-            if ($this->_objectManager->get('Magento\Checkout\Helper\Cart')->getShouldRedirectToCart()) {
-                $redirectUrl = $this->_objectManager->get('Magento\Checkout\Helper\Cart')->getCartUrl();
+            if ($this->cart->getShouldRedirectToCart()) {
+                $redirectUrl = $this->cart->getCartUrl();
             } else {
                 $refererUrl = $this->_redirect->getRefererUrl();
-                if ($refererUrl &&
-                    ($refererUrl != $this->_objectManager->get('Magento\Framework\UrlInterface')
-                            ->getUrl('*/*/configure/', ['id' => $item->getId()])
-                    )
-                ) {
+                if ($refererUrl && $refererUrl != $configureUrl) {
                     $redirectUrl = $refererUrl;
                 }
             }
-            $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate();
         } catch (\Magento\Framework\Model\Exception $e) {
             if ($e->getCode() == \Magento\Wishlist\Model\Item::EXCEPTION_CODE_NOT_SALABLE) {
                 $this->messageManager->addError(__('This product(s) is out of stock.'));
             } elseif ($e->getCode() == \Magento\Wishlist\Model\Item::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS) {
                 $this->messageManager->addNotice($e->getMessage());
-                $redirectUrl = $this->_url->getUrl('*/*/configure/', ['id' => $item->getId()]);
+                $redirectUrl = $configureUrl;
             } else {
                 $this->messageManager->addNotice($e->getMessage());
-                $redirectUrl = $this->_url->getUrl('*/*/configure/', ['id' => $item->getId()]);
+                $redirectUrl = $configureUrl;
             }
         } catch (\Exception $e) {
             $this->messageManager->addException($e, __('Cannot add item to shopping cart'));
         }
 
-        $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate();
+        $this->helper->calculate();
 
         return $this->getResponse()->setRedirect($redirectUrl);
     }
diff --git a/app/code/Magento/Wishlist/Controller/Index/Configure.php b/app/code/Magento/Wishlist/Controller/Index/Configure.php
index d7539cd2046fef16e1c171f13c6f0ce0c997b45c..56e56caff33dbbe1d42765a85ab9aa23dd817176 100644
--- a/app/code/Magento/Wishlist/Controller/Index/Configure.php
+++ b/app/code/Magento/Wishlist/Controller/Index/Configure.php
@@ -99,7 +99,7 @@ class Configure extends Action\Action implements IndexInterface
             return;
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t configure the product.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             $this->_redirect('*');
             return;
         }
diff --git a/app/code/Magento/Wishlist/Controller/Index/Update.php b/app/code/Magento/Wishlist/Controller/Index/Update.php
index 3b0e7b58f0915c8369dd906d4bed86525e579042..40c1e7dbee43ab811d4f795315879e322531465c 100644
--- a/app/code/Magento/Wishlist/Controller/Index/Update.php
+++ b/app/code/Magento/Wishlist/Controller/Index/Update.php
@@ -94,7 +94,7 @@ class Update extends Action\Action implements IndexInterface
                     try {
                         $item->delete();
                     } catch (\Exception $e) {
-                        $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+                        $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
                         $this->messageManager->addError(__('Can\'t delete item from wishlist'));
                     }
                 }
diff --git a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php
index cc5893c55da6afc5e23fe7408d2410c4266047a5..8d6046d6e938a7f8848699341723974ecb770e1f 100644
--- a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php
+++ b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php
@@ -99,7 +99,7 @@ class UpdateItemOptions extends Action\Action implements IndexInterface
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
             $this->messageManager->addError(__('An error occurred while updating wish list.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
         }
         $this->_redirect('*/*', ['wishlist_id' => $wishlist->getId()]);
     }
diff --git a/app/code/Magento/Wishlist/Model/ItemCarrier.php b/app/code/Magento/Wishlist/Model/ItemCarrier.php
index 07a014b3ff59fc6a90ad537cbdfbf4700501001f..a492568b03d805de7eda791827577bb4ea24d04d 100644
--- a/app/code/Magento/Wishlist/Model/ItemCarrier.php
+++ b/app/code/Magento/Wishlist/Model/ItemCarrier.php
@@ -9,7 +9,7 @@ use Magento\Checkout\Helper\Cart as CartHelper;
 use Magento\Checkout\Model\Cart;
 use Magento\Customer\Model\Session;
 use Magento\Framework\App\Response\RedirectInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Message\ManagerInterface as MessageManager;
 use Magento\Framework\UrlInterface;
 use Magento\Wishlist\Helper\Data as WishlistHelper;
@@ -32,7 +32,7 @@ class ItemCarrier
     protected $cart;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -145,7 +145,7 @@ class ItemCarrier
                     $cart->getQuote()->deleteItem($cartItem);
                 }
             } catch (\Exception $e) {
-                $this->logger->logException($e);
+                $this->logger->critical($e);
                 $messages[] = __('We cannot add this item to your shopping cart.');
             }
         }
diff --git a/app/code/Magento/Wishlist/Model/Resource/Item/Collection.php b/app/code/Magento/Wishlist/Model/Resource/Item/Collection.php
index 73bfe66eedfdb439d58baca9ccbe3bf400392095..8ab2536a38ad7ca14b72a6387e13bcc39cc92003 100644
--- a/app/code/Magento/Wishlist/Model/Resource/Item/Collection.php
+++ b/app/code/Magento/Wishlist/Model/Resource/Item/Collection.php
@@ -131,7 +131,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration
@@ -153,7 +153,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration,
diff --git a/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php b/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php
index c785b0fff90150aa222239de07ffdd576c1be9ce..06c7bd3b58e577d8f66f089f2ce3c3f468fc9d02 100644
--- a/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php
+++ b/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php
@@ -19,7 +19,7 @@ class Grid extends \Magento\Wishlist\Model\Resource\Item\Collection
 
     /**
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration
@@ -42,7 +42,7 @@ class Grid extends \Magento\Wishlist\Model\Resource\Item\Collection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration,
diff --git a/app/code/Magento/Wishlist/composer.json b/app/code/Magento/Wishlist/composer.json
index 263a9b27f3f392c9ca52e17f407ba677ede1d8b5..d72686c8a1e3e5176f73f9b36db8538f3841489c 100644
--- a/app/code/Magento/Wishlist/composer.json
+++ b/app/code/Magento/Wishlist/composer.json
@@ -3,28 +3,28 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/module-store": "0.42.0-beta1",
-        "magento/module-customer": "0.42.0-beta1",
-        "magento/module-catalog": "0.42.0-beta1",
-        "magento/module-core": "0.42.0-beta1",
-        "magento/module-checkout": "0.42.0-beta1",
-        "magento/module-theme": "0.42.0-beta1",
-        "magento/module-catalog-inventory": "0.42.0-beta1",
-        "magento/module-rss": "0.42.0-beta1",
-        "magento/module-backend": "0.42.0-beta1",
-        "magento/module-sales": "0.42.0-beta1",
-        "magento/module-grouped-product": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
-        "magento/module-ui": "0.42.0-beta1",
+        "magento/module-store": "0.42.0-beta2",
+        "magento/module-customer": "0.42.0-beta2",
+        "magento/module-catalog": "0.42.0-beta2",
+        "magento/module-core": "0.42.0-beta2",
+        "magento/module-checkout": "0.42.0-beta2",
+        "magento/module-theme": "0.42.0-beta2",
+        "magento/module-catalog-inventory": "0.42.0-beta2",
+        "magento/module-rss": "0.42.0-beta2",
+        "magento/module-backend": "0.42.0-beta2",
+        "magento/module-sales": "0.42.0-beta2",
+        "magento/module-grouped-product": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
+        "magento/module-ui": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "suggest": {
-        "magento/module-configurable-product": "0.42.0-beta1",
-        "magento/module-downloadable": "0.42.0-beta1",
-        "magento/module-bundle": "0.42.0-beta1"
+        "magento/module-configurable-product": "0.42.0-beta2",
+        "magento/module-downloadable": "0.42.0-beta2",
+        "magento/module-bundle": "0.42.0-beta2"
     },
     "type": "magento2-module",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/code/Magento/Wishlist/i18n/de_DE.csv b/app/code/Magento/Wishlist/i18n/de_DE.csv
index 43fc5de10f58cd7d56db31beb798c1000f58ffc8..364939cebbb084d7898b300060311b23bf45dab1 100644
--- a/app/code/Magento/Wishlist/i18n/de_DE.csv
+++ b/app/code/Magento/Wishlist/i18n/de_DE.csv
@@ -7,7 +7,7 @@ Action,Action
 "Are you sure that you want to remove this item?","Are you sure that you want to remove this item?"
 Edit,Bearbeiten
 "Remove item","Artikel löschen"
-"Add to Cart","Zum Warenkobrn hinzufügen"
+"Add to Cart","Zum Warenkorb hinzufügen"
 Delete,Delete
 Enabled,Enabled
 "We cannot add this item to your shopping cart.","We cannot add this item to your shopping cart."
diff --git a/app/design/adminhtml/Magento/backend/composer.json b/app/design/adminhtml/Magento/backend/composer.json
index c1176fc6fb42f3322363c8e95d7cfb219d3ff7a6..25b1fd38c70e0028b160ba06829f8ca19bff38c1 100644
--- a/app/design/adminhtml/Magento/backend/composer.json
+++ b/app/design/adminhtml/Magento/backend/composer.json
@@ -3,11 +3,11 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-theme",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/design/frontend/Magento/blank/composer.json b/app/design/frontend/Magento/blank/composer.json
index 313d99a4265cf89a3b6cb1a3d2b5be0bbd061749..ddfe84f6f985e66f47925bb30acc47773bb01baf 100644
--- a/app/design/frontend/Magento/blank/composer.json
+++ b/app/design/frontend/Magento/blank/composer.json
@@ -3,11 +3,11 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-theme",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/design/frontend/Magento/luma/composer.json b/app/design/frontend/Magento/luma/composer.json
index 706b30393451156855577ab4783191d925dcd47b..f4ae793c2219c29fe0a16d7f84dcb7a6ed2190af 100644
--- a/app/design/frontend/Magento/luma/composer.json
+++ b/app/design/frontend/Magento/luma/composer.json
@@ -3,12 +3,12 @@
     "description": "N/A",
     "require": {
         "php": "~5.4.11|~5.5.0",
-        "magento/theme-frontend-blank": "0.42.0-beta1",
-        "magento/framework": "0.42.0-beta1",
+        "magento/theme-frontend-blank": "0.42.0-beta2",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-theme",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/app/etc/di.xml b/app/etc/di.xml
index 11bb9ee59bbfd3b9594f97dd2fef3ad361e791a8..5fa642e9363e644b6821f21ffacc8395d05d1c65 100644
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -5,6 +5,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Psr\Log\LoggerInterface" type="Magento\Framework\Logger\Monolog" />
     <preference for="Magento\Framework\ObjectManager\FactoryInterface" type="Magento\Framework\ObjectManager\Factory\Dynamic\Developer" />
     <preference for="Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface" type="Magento\Framework\Search\Adapter\Mysql\Filter\Preprocessor" />
     <preference for="Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface" type="Magento\Framework\Search\Adapter\Mysql\Field\Resolver" />
@@ -85,6 +86,26 @@
     <preference for="Magento\Framework\DB\LoggerInterface" type="Magento\Framework\DB\Logger\Null"/>
     <preference for="Magento\Framework\App\Resource\ConnectionAdapterInterface" type="Magento\Framework\Model\Resource\Type\Db\Pdo\Mysql"/>
     <preference for="Magento\Framework\DB\QueryInterface" type="Magento\Framework\DB\Query"/>
+    <type name="Magento\Framework\Logger\Handler\System">
+        <arguments>
+            <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Framework\Logger\Monolog">
+        <arguments>
+            <argument name="name" xsi:type="string">main</argument>
+            <argument name="handlers"  xsi:type="array">
+                <item name="exception" xsi:type="object">Magento\Framework\Logger\Handler\Critical</item>
+                <item name="system" xsi:type="object">Magento\Framework\Logger\Handler\System</item>
+                <item name="debug" xsi:type="object">Magento\Framework\Logger\Handler\Debug</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Monolog\Handler\StreamHandler">
+        <arguments>
+            <argument name="stream" xsi:type="string">var/log/system.log</argument>
+        </arguments>
+    </type>
     <type name="Magento\Framework\Model\Context">
         <arguments>
             <argument name="actionValidator" xsi:type="object">Magento\Framework\Model\ActionValidator\RemoveAction\Proxy</argument>
diff --git a/app/i18n/magento/de_de/composer.json b/app/i18n/magento/de_de/composer.json
index 6c7118d89984e2fb7fbf9058c29e46a38ea91eaf..a7bdff2a6f0578fe45f4111eba662f16c8d27da6 100644
--- a/app/i18n/magento/de_de/composer.json
+++ b/app/i18n/magento/de_de/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-de_de",
     "description": "German (Germany) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/en_us/composer.json b/app/i18n/magento/en_us/composer.json
index 7ffb52d829f96c4c8e87c8eb0208ddf3b25a97f7..19d2f4bffa41eb88483d8de046c8b012d6b40aa0 100644
--- a/app/i18n/magento/en_us/composer.json
+++ b/app/i18n/magento/en_us/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-en_us",
     "description": "English (United States) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/es_es/composer.json b/app/i18n/magento/es_es/composer.json
index f99489d51672b72e991034d3970972be277e9629..ff330bcfc2e78ae61704d31a25b381a3b79f5514 100644
--- a/app/i18n/magento/es_es/composer.json
+++ b/app/i18n/magento/es_es/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-es_es",
     "description": "Spanish (Spain) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/fr_fr/composer.json b/app/i18n/magento/fr_fr/composer.json
index bda3533f63981b604b3a5a72d279c8a47ec12d8b..97e699096cf5acfaf64969cc98742ac98cb9e017 100644
--- a/app/i18n/magento/fr_fr/composer.json
+++ b/app/i18n/magento/fr_fr/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-fr_fr",
     "description": "French (France) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/nl_nl/composer.json b/app/i18n/magento/nl_nl/composer.json
index 357991fb1e47d1ec7c8f6d6c731261ccd6cc9a9e..7aac45fbaed9dc0d353e55bbe2554e102ef1e3bd 100644
--- a/app/i18n/magento/nl_nl/composer.json
+++ b/app/i18n/magento/nl_nl/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-nl_nl",
     "description": "Dutch (Netherlands) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/pt_br/composer.json b/app/i18n/magento/pt_br/composer.json
index 1ce0e7526d9da49bbf36755407808fe18115e797..7cd46208ae661d5f9d0fda890443673170bc38cc 100644
--- a/app/i18n/magento/pt_br/composer.json
+++ b/app/i18n/magento/pt_br/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-pt_br",
     "description": "Portuguese (Brazil) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/app/i18n/magento/zh_cn/composer.json b/app/i18n/magento/zh_cn/composer.json
index 06cb1f677bdacade0817ed060404eb01bf00f115..d04f7afd3ddaa71c81e0886fa96bf1b7c7890942 100644
--- a/app/i18n/magento/zh_cn/composer.json
+++ b/app/i18n/magento/zh_cn/composer.json
@@ -1,13 +1,13 @@
 {
     "name": "magento/language-zh_cn",
     "description": "Chinese (China) language",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
-        "magento/framework": "0.42.0-beta1",
+        "magento/framework": "0.42.0-beta2",
         "magento/magento-composer-installer": "*"
     },
     "type": "magento2-language",
diff --git a/composer.json b/composer.json
index fc63f5b4ac65fa09574d4e3d69f82ab5b2c21bf0..4f7d10574a1ab9a6a99c881160014a20b059cbe9 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/project-community-edition",
     "description": "Magento project (Community Edition)",
     "type": "project",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
@@ -30,7 +30,8 @@
         "zendframework/zend-log": "2.3.1",
         "zendframework/zend-http": "2.3.1",
         "magento/zendframework1": "1.12.9-patch1",
-        "composer/composer": "1.0.0-alpha8"
+        "composer/composer": "1.0.0-alpha8",
+        "monolog/monolog": "1.11.0"
     },
     "require-dev": {
         "phpunit/phpunit": "4.1.0",
@@ -47,7 +48,8 @@
         "ext-curl": "*",
         "ext-iconv": "*",
         "sjparkinson/static-review": "~4.1",
-        "fabpot/php-cs-fixer": "~1.2"
+        "fabpot/php-cs-fixer": "~1.2",
+        "lusitanian/oauth": "~0.3"
     },
     "replace": {
         "magento/module-admin-notification": "self.version",
diff --git a/composer.lock b/composer.lock
index 7cb7c6f857a442535a10bf2c75a3e5c0803611bd..990692a84d28d499a7b9a0b3c3e06b19eabecc7e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "cf88c5db8e11255eb97498f788609028",
+    "hash": "0c7573953aece5e5227468ebff4539da",
     "packages": [
         {
             "name": "composer/composer",
@@ -178,6 +178,116 @@
             ],
             "time": "2014-12-12 15:28:16"
         },
+        {
+            "name": "monolog/monolog",
+            "version": "1.11.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Seldaek/monolog.git",
+                "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
+                "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "psr/log": "~1.0"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0.0"
+            },
+            "require-dev": {
+                "aws/aws-sdk-php": "~2.4, >2.4.8",
+                "doctrine/couchdb": "~1.0@dev",
+                "graylog2/gelf-php": "~1.0",
+                "phpunit/phpunit": "~3.7.0",
+                "raven/raven": "~0.5",
+                "ruflin/elastica": "0.90.*",
+                "videlalvaro/php-amqplib": "~2.4"
+            },
+            "suggest": {
+                "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+                "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+                "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+                "ext-mongo": "Allow sending log messages to a MongoDB server",
+                "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+                "raven/raven": "Allow sending log messages to a Sentry server",
+                "rollbar/rollbar": "Allow sending log messages to Rollbar",
+                "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+                "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.11.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Monolog\\": "src/Monolog"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+            "homepage": "http://github.com/Seldaek/monolog",
+            "keywords": [
+                "log",
+                "logging",
+                "psr-3"
+            ],
+            "time": "2014-09-30 13:30:58"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
+                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Psr\\Log\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "time": "2012-12-21 11:40:51"
+        },
         {
             "name": "seld/jsonlint",
             "version": "1.3.0",
@@ -1813,6 +1923,68 @@
             ],
             "time": "2014-11-08 02:33:31"
         },
+        {
+            "name": "lusitanian/oauth",
+            "version": "v0.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Lusitanian/PHPoAuthLib.git",
+                "reference": "ac5a1cd5a4519143728dce2213936eea302edf8a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/ac5a1cd5a4519143728dce2213936eea302edf8a",
+                "reference": "ac5a1cd5a4519143728dce2213936eea302edf8a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "3.7.*",
+                "predis/predis": "0.8.*@dev",
+                "symfony/http-foundation": "~2.1"
+            },
+            "suggest": {
+                "ext-openssl": "Allows for usage of secure connections with the stream-based HTTP client.",
+                "predis/predis": "Allows using the Redis storage backend.",
+                "symfony/http-foundation": "Allows using the Symfony Session storage backend."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "OAuth": "src",
+                    "OAuth\\Unit": "tests"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "David Desberg",
+                    "email": "david@daviddesberg.com"
+                },
+                {
+                    "name": "Pieter Hordijk",
+                    "email": "info@pieterhordijk.com"
+                }
+            ],
+            "description": "PHP 5.3+ oAuth 1/2 Library",
+            "keywords": [
+                "Authentication",
+                "authorization",
+                "oauth",
+                "security"
+            ],
+            "time": "2014-09-05 15:19:58"
+        },
         {
             "name": "pdepend/pdepend",
             "version": "2.0.4",
@@ -1891,16 +2063,16 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "2.0.13",
+            "version": "2.0.14",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5"
+                "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5",
-                "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca158276c1200cc27f5409a5e338486bc0b4fc94",
+                "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94",
                 "shasum": ""
             },
             "require": {
@@ -1952,7 +2124,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2014-12-03 06:41:44"
+            "time": "2014-12-26 13:28:33"
         },
         {
             "name": "phpunit/php-file-iterator",
diff --git a/dev/tests/api-functional/.gitignore b/dev/tests/api-functional/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..77d5f53390c6c26ad0b8b00ad8dd577abedf89e8
--- /dev/null
+++ b/dev/tests/api-functional/.gitignore
@@ -0,0 +1,3 @@
+/*.xml
+/var/
+/config/*.php
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester.php b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6bc716ff5529448ef5542c12cbe4ff0c93f05a8
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Controller;
+
+use Magento\Framework\App\RequestInterface;
+use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
+use Magento\Framework\Stdlib\Cookie\PhpCookieManager;
+
+/**
+ * Controller for testing the CookieManager.
+ *
+ */
+class CookieTester extends \Magento\Framework\App\Action\Action
+{
+    /** @var PhpCookieManager */
+    protected $cookieManager;
+
+    /** @var  CookieMetadataFactory */
+    protected $cookieMetadataFactory;
+
+    /**
+     * @param \Magento\Framework\App\Action\Context $context
+     * @param PhpCookieManager $cookieManager
+     * @param CookieMetadataFactory $cookieMetadataFactory
+     */
+    public function __construct(
+        \Magento\Framework\App\Action\Context $context,
+        PhpCookieManager $cookieManager,
+        CookieMetadataFactory $cookieMetadataFactory
+    ) {
+        $this->cookieManager = $cookieManager;
+        $this->cookieMetadataFacory = $cookieMetadataFactory;
+        parent::__construct($context);
+    }
+
+    /**
+     * Retrieve cookie metadata factory
+     */
+    protected function getCookieMetadataFactory()
+    {
+        return $this->cookieMetadataFacory;
+    }
+
+    /**
+     * Retrieve cookie metadata factory
+     */
+    protected function getCookieManager()
+    {
+        return $this->cookieManager;
+    }
+
+    /**
+     * Dispatch request
+     *
+     * @param RequestInterface $request
+     * @return \Magento\Framework\App\ResponseInterface
+     */
+    public function dispatch(RequestInterface $request)
+    {
+        if (!$this->getRequest()->isDispatched()) {
+            parent::dispatch($request);
+        }
+
+        $result = parent::dispatch($request);
+        return $result;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/DeleteCookie.php b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/DeleteCookie.php
new file mode 100644
index 0000000000000000000000000000000000000000..f7ef99d6b520524f9a088367d6c46ab3df9e47b3
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/DeleteCookie.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Controller\CookieTester;
+
+/**
+ * Controller to test deletion of a cookie
+ */
+class DeleteCookie extends \Magento\TestModule1\Controller\CookieTester
+{
+    /**
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        $cookieName = $this->getRequest()->getParam('cookie_name');
+        $this->getCookieManager()->deleteCookie($cookieName);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetPublicCookie.php b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetPublicCookie.php
new file mode 100644
index 0000000000000000000000000000000000000000..c72395edf16c766a7db3a8306c389ea704072932
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetPublicCookie.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Controller\CookieTester;
+
+/**
+ */
+class SetPublicCookie extends \Magento\TestModule1\Controller\CookieTester
+{
+    /**
+     * Sets a public cookie with data from url parameters
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        $publicCookieMetadata = $this->getCookieMetadataFactory()->createPublicCookieMetadata();
+
+        $cookieDomain = $this->getRequest()->getParam('cookie_domain');
+        if ($cookieDomain !== null) {
+            $publicCookieMetadata->setDomain($cookieDomain);
+        }
+
+        $cookiePath = $this->getRequest()->getParam('cookie_path');
+        if ($cookiePath !== null) {
+            $publicCookieMetadata->setPath($cookiePath);
+        }
+
+        $cookieDuration = $this->getRequest()->getParam('cookie_duration');
+        if ($cookieDuration !== null) {
+            $publicCookieMetadata->setDuration($cookieDuration);
+        }
+
+        $httpOnly = $this->getRequest()->getParam('cookie_httponly');
+        if ($httpOnly !== null) {
+            $publicCookieMetadata->setHttpOnly($httpOnly);
+        }
+
+        $secure = $this->getRequest()->getParam('cookie_secure');
+        if ($secure !== null) {
+            $publicCookieMetadata->setSecure($secure);
+        }
+
+        $cookieName = $this->getRequest()->getParam('cookie_name');
+        $cookieValue = $this->getRequest()->getParam('cookie_value');
+        $this->getCookieManager()->setPublicCookie($cookieName, $cookieValue, $publicCookieMetadata);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetSensitiveCookie.php b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetSensitiveCookie.php
new file mode 100644
index 0000000000000000000000000000000000000000..3cb0d47fae43535e7fdda6799e0a7aa4d037eb6f
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Controller/CookieTester/SetSensitiveCookie.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Controller\CookieTester;
+
+/**
+ */
+class SetSensitiveCookie extends \Magento\TestModule1\Controller\CookieTester
+{
+    /**
+     * Sets a sensitive cookie with data from url parameters
+     *
+     * @return void
+     */
+    public function execute()
+    {
+        $sensitiveCookieMetadata = $this->getCookieMetadataFactory()->createSensitiveCookieMetadata();
+
+        $cookieDomain = $this->getRequest()->getParam('cookie_domain');
+        if ($cookieDomain !== null) {
+            $sensitiveCookieMetadata->setDomain($cookieDomain);
+        }
+        $cookiePath = $this->getRequest()->getParam('cookie_domain');
+        if ($cookiePath !== null) {
+            $sensitiveCookieMetadata->setPath($cookiePath);
+        }
+
+        $cookieName = $this->getRequest()->getParam('cookie_name');
+        $cookieValue = $this->getRequest()->getParam('cookie_value');
+        $this->getCookieManager()->setSensitiveCookie($cookieName, $cookieValue, $sensitiveCookieMetadata);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..025d819004d0658f650faf8b0a1bcad6fbff4eb7
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRest.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1;
+
+use Magento\TestModule1\Service\V1\Entity\CustomAttributeDataObjectBuilder;
+use Magento\TestModule1\Service\V1\Entity\Item;
+use Magento\TestModule1\Service\V1\Entity\ItemBuilder;
+
+class AllSoapAndRest implements \Magento\TestModule1\Service\V1\AllSoapAndRestInterface
+{
+    /**
+     * @var ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @var CustomAttributeDataObjectBuilder
+     */
+    protected $customAttributeDataObjectBuilder;
+
+    /**
+     * @param ItemBuilder $itemBuilder
+     * @param CustomAttributeDataObjectBuilder $customAttributeNestedDataObjectBuilder
+     */
+    public function __construct(
+        ItemBuilder $itemBuilder,
+        CustomAttributeDataObjectBuilder $customAttributeNestedDataObjectBuilder
+    ) {
+        $this->itemBuilder = $itemBuilder;
+        $this->customAttributeDataObjectBuilder = $customAttributeNestedDataObjectBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($itemId)
+    {
+        return $this->itemBuilder->setItemId($itemId)->setName('testProduct1')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items()
+    {
+        $result1 = $this->itemBuilder->setItemId(1)->setName('testProduct1')->create();
+        $result2 = $this->itemBuilder->setItemId(2)->setName('testProduct2')->create();
+
+        return [$result1, $result2];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create($name)
+    {
+        return $this->itemBuilder->setItemId(rand())->setName($name)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(Item $entityItem)
+    {
+        return $this->itemBuilder->setItemId($entityItem->getItemId())
+            ->setName('Updated' . $entityItem->getName())
+            ->create();
+    }
+
+    public function testOptionalParam($name = null)
+    {
+        if (is_null($name)) {
+            return $this->itemBuilder->setItemId(3)->setName('No Name')->create();
+        } else {
+            return $this->itemBuilder->setItemId(3)->setName($name)->create();
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function itemAnyType(Item $item)
+    {
+        return $item;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPreconfiguredItem()
+    {
+        $customAttributeDataObject = $this->customAttributeDataObjectBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        return $item;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..d43d1553561de2d74d9fd4fcf6a271b124f02a1d
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/AllSoapAndRestInterface.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1;
+
+use Magento\TestModule1\Service\V1\Entity\Item;
+
+interface AllSoapAndRestInterface
+{
+    /**
+     * @param int $itemId
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function item($itemId);
+
+    /**
+     * @param string $name
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function create($name);
+
+    /**
+     * @param \Magento\TestModule1\Service\V1\Entity\Item $entityItem
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function update(Item $entityItem);
+
+    /**
+     * @return \Magento\TestModule1\Service\V1\Entity\Item[]
+     */
+    public function items();
+
+    /**
+     * @param string $name
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function testOptionalParam($name = null);
+
+    /**
+     * @param \Magento\TestModule1\Service\V1\Entity\Item $entityItem
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function itemAnyType(Item $entityItem);
+
+    /**
+     * @return \Magento\TestModule1\Service\V1\Entity\Item
+     */
+    public function getPreconfiguredItem();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObject.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3cf77d44933f6d2811611705205d48117a61b94
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObject.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class CustomAttributeDataObject extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObjectBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObjectBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..e128de99359f774aa1508e4b08252b1f179c678d
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeDataObjectBuilder.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class CustomAttributeDataObjectBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param string $name
+     *
+     * @return $this
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObject.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b439713fafdcecd9bcb3e1fe3073b9381cda4fb
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObject.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class CustomAttributeNestedDataObject extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObjectBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObjectBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bf501ac727da54c801558326e1aa21254292b02
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/CustomAttributeNestedDataObjectBuilder.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class CustomAttributeNestedDataObjectBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param string $name
+     *
+     * @return $this
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadata.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadata.php
new file mode 100644
index 0000000000000000000000000000000000000000..134623a864f693e9d8a755b46808602970bd066c
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadata.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity\Eav;
+
+use Magento\Framework\Api\AbstractExtensibleObject;
+use Magento\Framework\Api\MetadataObjectInterface;
+
+/**
+ * Class AttributeMetadata
+ */
+class AttributeMetadata extends AbstractExtensibleObject implements MetadataObjectInterface
+{
+    /**#@+
+     * Constants used as keys into $_data
+     */
+    const ATTRIBUTE_ID = 'attribute_id';
+
+    const ATTRIBUTE_CODE = 'attribute_code';
+    /**#@-*/
+
+    /**
+     * Retrieve id of the attribute.
+     *
+     * @return string|null
+     */
+    public function getAttributeId()
+    {
+        return $this->_get(self::ATTRIBUTE_ID);
+    }
+
+    /**
+     * Retrieve code of the attribute.
+     *
+     * @return string|null
+     */
+    public function getAttributeCode()
+    {
+        return $this->_get(self::ATTRIBUTE_CODE);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadataBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadataBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..b96ef2b4f5da204af0511149eea26edd36d4ec4f
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Eav/AttributeMetadataBuilder.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity\Eav;
+
+use Magento\Framework\Api\AttributeMetadataBuilderInterface;
+use Magento\Framework\Api\ExtensibleObjectBuilder;
+
+/**
+ * Class AttributeMetadataBuilder
+ */
+class AttributeMetadataBuilder extends ExtensibleObjectBuilder implements AttributeMetadataBuilderInterface
+{
+    /**
+     * Set attribute id
+     *
+     * @param  int $attributeId
+     * @return $this
+     */
+    public function setAttributeId($attributeId)
+    {
+        return $this->_set(AttributeMetadata::ATTRIBUTE_ID, $attributeId);
+    }
+
+    /**
+     * Set attribute code
+     *
+     * @param  string $attributeCode
+     * @return $this
+     */
+    public function setAttributeCode($attributeCode)
+    {
+        return $this->_set(AttributeMetadata::ATTRIBUTE_CODE, $attributeCode);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Item.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..d307ac8f6a8d1fe71a808b529e913df7d4f74cfe
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/Item.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class Item extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return int
+     */
+    public function getItemId()
+    {
+        return $this->_data['item_id'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/ItemBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/ItemBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..c13fd4b8e898074d2dade57b556e7e668ad92a03
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V1/Entity/ItemBuilder.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V1\Entity;
+
+class ItemBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**#@+
+     * Custom attribute code constants
+     */
+    const CUSTOM_ATTRIBUTE_1 = 'custom_attribute1';
+    const CUSTOM_ATTRIBUTE_2 = 'custom_attribute2';
+    const CUSTOM_ATTRIBUTE_3 = 'custom_attribute3';
+    /**#@-*/
+
+    /**
+     * @param int $itemId
+     *
+     * @return \Magento\TestModule1\Service\V1\Entity\ItemBuilder
+     */
+    public function setItemId($itemId)
+    {
+        $this->data['item_id'] = $itemId;
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     *
+     * @return \Magento\TestModule1\Service\V1\Entity\ItemBuilder
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+
+    /**
+     * Template method used to configure the attribute codes for the custom attributes
+     *
+     * @return string[]
+     */
+    public function getCustomAttributesCodes()
+    {
+        return array_merge(
+            parent::getCustomAttributesCodes(),
+            [self::CUSTOM_ATTRIBUTE_1, self::CUSTOM_ATTRIBUTE_2, self::CUSTOM_ATTRIBUTE_3]
+        );
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef17f0c5749bef4262d3e9c1f5acb09445f69c0b
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V2;
+
+use Magento\TestModule1\Service\V2\Entity\Item;
+use Magento\TestModule1\Service\V2\Entity\ItemBuilder;
+
+class AllSoapAndRest implements \Magento\TestModule1\Service\V2\AllSoapAndRestInterface
+{
+    /**
+     * @var ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @param ItemBuilder $itemBuilder
+     */
+    public function __construct(ItemBuilder $itemBuilder)
+    {
+        $this->itemBuilder = $itemBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($id)
+    {
+        return $this->itemBuilder->setId($id)->setName('testProduct1')->setPrice('1')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items($filters = [], $sortOrder = 'ASC')
+    {
+        $result = [];
+        $firstItem = $this->itemBuilder->setId(1)->setName('testProduct1')->setPrice('1')->create();
+        $secondItem = $this->itemBuilder->setId(2)->setName('testProduct2')->setPrice('2')->create();
+
+        /** Simple filtration implementation */
+        if (!empty($filters)) {
+            /** @var \Magento\Framework\Api\Filter $filter */
+            foreach ($filters as $filter) {
+                if ('id' == $filter->getField() && $filter->getValue() == 1) {
+                    $result[] = $firstItem;
+                } elseif ('id' == $filter->getField() && $filter->getValue() == 2) {
+                    $result[] = $secondItem;
+                }
+            }
+        } else {
+            /** No filter is specified. */
+            $result = [$firstItem, $secondItem];
+        }
+        return $result;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create($name)
+    {
+        return $this->itemBuilder->setId(rand())->setName($name)->setPrice('10')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(Item $entityItem)
+    {
+        return $this->itemBuilder
+            ->setId($entityItem->getId())
+            ->setName('Updated' . $entityItem->getName())
+            ->setPrice('5')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function delete($id)
+    {
+        return $this->itemBuilder->setId($id)->setName('testProduct1')->setPrice('1')->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0507a01422b72fbc9c0af63aaf1800c592a10dcf
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/AllSoapAndRestInterface.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V2;
+
+use Magento\TestModule1\Service\V2\Entity\Item;
+
+interface AllSoapAndRestInterface
+{
+    /**
+     * Get item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule1\Service\V2\Entity\Item
+     */
+    public function item($id);
+
+    /**
+     * Create item.
+     *
+     * @param string $name
+     * @return \Magento\TestModule1\Service\V2\Entity\Item
+     */
+    public function create($name);
+
+    /**
+     * Update item.
+     *
+     * @param \Magento\TestModule1\Service\V2\Entity\Item $entityItem
+     * @return \Magento\TestModule1\Service\V2\Entity\Item
+     */
+    public function update(Item $entityItem);
+
+    /**
+     * Retrieve a list of items.
+     *
+     * @param \Magento\Framework\Api\Filter[] $filters
+     * @param string $sortOrder
+     * @return \Magento\TestModule1\Service\V2\Entity\Item[]
+     */
+    public function items($filters = [], $sortOrder = 'ASC');
+
+    /**
+     * Delete an item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule1\Service\V2\Entity\Item
+     */
+    public function delete($id);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/Item.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..79438931a5dd35aee7b9ac923dacfc14417189b8
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/Item.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V2\Entity;
+
+class Item extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->_data['id'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrice()
+    {
+        return $this->_data['price'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/ItemBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/ItemBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..d28d791b6b8fcf4a337000f01ff4db1ea7a7d5de
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/Service/V2/Entity/ItemBuilder.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule1\Service\V2\Entity;
+
+class ItemBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param int $id
+     *
+     * @return \Magento\TestModule1\Service\V2\Entity\ItemBuilder
+     */
+    public function setId($id)
+    {
+        $this->data['id'] = $id;
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     *
+     * @return \Magento\TestModule1\Service\V2\Entity\ItemBuilder
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+
+    /**
+     * @param string $price
+     *
+     * @return \Magento\TestModule1\Service\V2\Entity\ItemBuilder
+     */
+    public function setPrice($price)
+    {
+        $this->data['price'] = $price;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e6fcca6add8e3a5f1cb6ba3dd094507e532f0573
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/acl.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModule1::all" title="TestModule1" sortOrder="1">
+                    <resource id="Magento_TestModule1::resource1" title="Resource1" sortOrder="20"/>
+                    <resource id="Magento_TestModule1::resource2" title="Resource2" sortOrder="10"/>
+                    <resource id="Magento_TestModule1::resource3" title="Resource3" sortOrder="30"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f30038e83f43424f97cd1da59114a062ec27db19
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/data_object.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd">
+    <custom_attributes for="Magento\TestModule1\Service\V1\Entity\Item">
+        <attribute code="custom_attribute_data_object" type="Magento\TestModule1\Service\V1\Entity\CustomAttributeDataObject" />
+        <attribute code="custom_attribute_string" type="string" />
+    </custom_attributes>
+    <custom_attributes for="Magento\TestModule1\Service\V1\Entity\CustomAttributeDataObject">
+        <attribute code="custom_attribute_nested" type="Magento\TestModule1\Service\V1\Entity\CustomAttributeNestedDataObject" />
+        <attribute code="custom_attribute_int" type="int" />
+    </custom_attributes>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..977ca625f28c51fc95cbef8906214c51c5b6e62f
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" type="Magento\TestModule1\Service\V1\AllSoapAndRest" />
+    <preference for="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" type="Magento\TestModule1\Service\V2\AllSoapAndRest" />
+
+    <virtualType name="Magento\TestModule1\Service\Config\TestModule1MetadataConfig" type="Magento\Framework\Api\Config\MetadataConfig">
+        <arguments>
+            <argument name="attributeMetadataBuilder" xsi:type="object">Magento\TestModule1\Service\V1\Entity\Eav\AttributeMetadataBuilder</argument>
+            <argument name="dataObjectClassName" xsi:type="string">Magento\TestModule1\Service\V1\Entity\Item</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\TestModule1\Service\V1\Entity\ItemBuilder">
+        <arguments>
+            <argument name="metadataService" xsi:type="object">Magento\TestModule1\Service\Config\TestModule1MetadataConfig</argument>
+        </arguments>
+    </type>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/frontend/routes.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/frontend/routes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f6984e2d6d74dcb50b9e77f2d348d94ca405ef63
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/frontend/routes.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
+    <router id="standard">
+        <route id="testmoduleone" frontName="testmoduleone">
+            <module name="Magento_TestModule1" />
+        </route>
+    </router>
+</config>
\ No newline at end of file
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ba0d441958811635aaa373abe641378deefe97e2
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModule1" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..874afa7713840d9a7ed9015a033b4e556dd19ef6
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/webapi.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+
+    <route method="GET" url="/V1/testmodule1/overwritten">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+        </resources>
+        <data>
+            <parameter name="itemId" force="true">-55</parameter>
+        </data>
+    </route>
+
+    <route method="POST" url="/V1/testmodule1/testOptionalParam">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="testOptionalParam" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+        </resources>
+        <data>
+            <parameter name="name">Default Name</parameter>
+        </data>
+    </route>
+
+    <route method="GET" url="/V1/testmodule1/:itemId">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testmodule1">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmodule1">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="create" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource3" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V1/testmodule1/:itemId">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="update" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmodule1/itemAnyType">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="itemAnyType" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testmodule1/itemPreconfigured">
+        <service class="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" method="getPreconfiguredItem" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="GET" url="/V2/testmodule1/:id">
+        <service class="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V2/testmodule1">
+        <service class="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V2/testmodule1">
+        <service class="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" method="create" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource3" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V2/testmodule1/:id">
+        <service class="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" method="update" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+            <resource ref="Magento_TestModule1::resource2" />
+        </resources>
+    </route>
+    <route method="DELETE" url="/V2/testmodule1/:id">
+        <service class="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" method="delete" />
+        <resources>
+            <resource ref="Magento_TestModule1::resource1" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/Item.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac51c4663a5a779eb72741564a7533ab26a6a1d2
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/Item.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1\Entity;
+
+class Item extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->_data['id'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/ItemBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/ItemBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..79b57a34aec3e6f30bdb0cebb6bd7909d4c4095f
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/Entity/ItemBuilder.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1\Entity;
+
+class ItemBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param int $id
+     * @return \Magento\TestModule2\Service\V1\Entity\ItemBuilder
+     */
+    public function setId($id)
+    {
+        $this->data['id'] = $id;
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     * @return \Magento\TestModule2\Service\V1\Entity\ItemBuilder
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXml.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXml.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a1128502b8936b229283f756170b32ccb7cf6ca
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXml.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1;
+
+use Magento\TestModule2\Service\V1\Entity\Item;
+use Magento\TestModule2\Service\V1\Entity\ItemBuilder;
+
+class NoWebApiXml implements \Magento\TestModule2\Service\V1\NoWebApiXmlInterface
+{
+    /**
+     * @var ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @param ItemBuilder $itemBuilder
+     */
+    public function __construct(ItemBuilder $itemBuilder)
+    {
+        $this->itemBuilder = $itemBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($id)
+    {
+        return $this->itemBuilder->setId($id)->setName('testProduct1')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items()
+    {
+        $result1 = $this->itemBuilder->setId(1)->setName('testProduct1')->create();
+
+        $result2 = $this->itemBuilder->setId(2)->setName('testProduct2')->create();
+
+        return [$result1, $result2];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create($name)
+    {
+        return $this->itemBuilder->setId(rand())->setName($name)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(Item $item)
+    {
+        return $this->itemBuilder->setId($item->getId())->setName('Updated' . $item->getName())->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXmlInterface.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXmlInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..474ef888d510ed92a3ee29430ef984d5cbe3db7d
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/NoWebApiXmlInterface.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1;
+
+use Magento\TestModule2\Service\V1\Entity\Item;
+
+interface NoWebApiXmlInterface
+{
+    /**
+     * Get an item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function item($id);
+
+    /**
+     * Create an item.
+     *
+     * @param string $name
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function create($name);
+
+    /**
+     * Update an item.
+     *
+     * @param \Magento\TestModule2\Service\V1\Entity\Item $item
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function update(Item $item);
+
+    /**
+     * Retrieve a list of items.
+     *
+     * @return \Magento\TestModule2\Service\V1\Entity\Item[]
+     */
+    public function items();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRest.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0f6d5e9670aa730d3cd0c7ae3e9a1b7be0efe4dc
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1;
+
+use Magento\TestModule2\Service\V1\Entity\Item;
+use Magento\TestModule2\Service\V1\Entity\ItemBuilder;
+
+class SubsetRest implements \Magento\TestModule2\Service\V1\SubsetRestInterface
+{
+    /**
+     * @var ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @param ItemBuilder $itemBuilder
+     */
+    public function __construct(ItemBuilder $itemBuilder)
+    {
+        $this->itemBuilder = $itemBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($id)
+    {
+        return $this->itemBuilder->setId($id)->setName('testItem' . $id)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items()
+    {
+        $result1 = $this->itemBuilder->setId(1)->setName('testItem1')->create();
+
+        $result2 = $this->itemBuilder->setId(2)->setName('testItem2')->create();
+
+        return [$result1, $result2];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create($name)
+    {
+        return $this->itemBuilder->setId(rand())->setName($name)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(Item $item)
+    {
+        return $this->itemBuilder->setId($item->getId())->setName('Updated' . $item->getName())->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($id)
+    {
+        return $this->itemBuilder->setId(1)->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c52fd18fb55b8f8d7b227dab223291eaab298eb2
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/Service/V1/SubsetRestInterface.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule2\Service\V1;
+
+use Magento\TestModule2\Service\V1\Entity\Item;
+
+interface SubsetRestInterface
+{
+    /**
+     * Return a single item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function item($id);
+
+    /**
+     * Return multiple items.
+     *
+     * @return \Magento\TestModule2\Service\V1\Entity\Item[]
+     */
+    public function items();
+
+    /**
+     * Create an item.
+     *
+     * @param string $name
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function create($name);
+
+    /**
+     * Update an item.
+     *
+     * @param \Magento\TestModule2\Service\V1\Entity\Item $item
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function update(Item $item);
+
+    /**
+     * Delete an item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule2\Service\V1\Entity\Item
+     */
+    public function remove($id);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModule2/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d6b32a5bf83fb4ec80d8445d3a6688bd6b5d8ddc
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/acl.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModule2::all" title="TestModule2" sortOrder="1">
+                    <resource id="Magento_TestModule2::resource1" title="Resource1" sortOrder="20"/>
+                    <resource id="Magento_TestModule2::resource2" title="Resource2" sortOrder="10"/>
+                    <resource id="Magento_TestModule2::resource3" title="Resource3" sortOrder="30"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule2/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ffb7f082e52b06e8f7394958ef859f8f1fcb1a05
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/di.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\TestModule2\Service\V1\SubsetRestInterface" type="Magento\TestModule2\Service\V1\SubsetRest" />
+    <preference for="Magento\TestModule2\Service\V1\NoWebApiXmlInterface" type="Magento\TestModule2\Service\V1\NoWebApiXml" />
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6f6c90cfd914f30c214eba82cf3d97126e42ea60
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModule2" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/AllSoapNoRestV1.xsd b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/AllSoapNoRestV1.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..3e7caaa8d480048a83ea35018572ff62bf034ca9
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/AllSoapNoRestV1.xsd
@@ -0,0 +1,239 @@
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+    <xsd:complexType name="ItemRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="ItemResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Item call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="ItemsResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray"
+                         type="ItemsArray">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+
+    <xsd:complexType name="ItemsArray">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="CreateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="CreateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Create call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Update call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Remove call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+</xsd:schema>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/NoWebApiXmlV1.xsd b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/NoWebApiXmlV1.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..3e7caaa8d480048a83ea35018572ff62bf034ca9
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/NoWebApiXmlV1.xsd
@@ -0,0 +1,239 @@
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+    <xsd:complexType name="ItemRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="ItemResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Item call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="ItemsResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray"
+                         type="ItemsArray">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+
+    <xsd:complexType name="ItemsArray">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="CreateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="CreateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Create call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Update call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Remove call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+</xsd:schema>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/SubsetRestV1.xsd b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/SubsetRestV1.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..3e7caaa8d480048a83ea35018572ff62bf034ca9
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/schema/SubsetRestV1.xsd
@@ -0,0 +1,239 @@
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+    <xsd:complexType name="ItemRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="ItemResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Item call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="ItemsResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray"
+                         type="ItemsArray">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+
+    <xsd:complexType name="ItemsArray">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Items call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Items</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Item</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="CreateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="CreateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Create call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="name"  type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Create</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="UpdateResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Update call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Update</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveRequest">
+        <xsd:annotation>
+            <xsd:documentation/>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:int">
+                <xsd:annotation>
+                    <xsd:documentation>Entity ID</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:min/>
+                        <inf:max/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:requiredInput>Yes</inf:requiredInput>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    <xsd:complexType name="RemoveResponse">
+        <xsd:annotation>
+            <xsd:documentation>Response container for the Remove call.</xsd:documentation>
+            <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap"/>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="id" type="xsd:string">
+                <xsd:annotation>
+                    <xsd:documentation>Default label</xsd:documentation>
+                    <xsd:appinfo xmlns:inf="http://magento.ll/webapi/soap">
+                        <inf:maxLength/>
+                        <inf:callInfo>
+                            <inf:callName>Remove</inf:callName>
+                            <inf:returned>Always</inf:returned>
+                        </inf:callInfo>
+                    </xsd:appinfo>
+                </xsd:annotation>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+</xsd:schema>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule2/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModule2/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fb4339826d5d1926d0947ab4ffa5b79556b763d3
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule2/etc/webapi.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route method="GET" url="/V1/testModule2SubsetRest/:id">
+        <service class="Magento\TestModule2\Service\V1\SubsetRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule2::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testModule2SubsetRest">
+        <service class="Magento\TestModule2\Service\V1\SubsetRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModule2::resource2" />
+            <resource ref="Magento_TestModule2::resource3" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/Parameter.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/Parameter.php
new file mode 100644
index 0000000000000000000000000000000000000000..a6f58178d0453ba3dab9ae658c8dbf3124b4d0d9
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/Parameter.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule3\Service\V1\Entity;
+
+class Parameter extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * Get Name.
+     *
+     * @return string $name
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+
+    /**
+     * Get value.
+     *
+     * @return string $value
+     */
+    public function getValue()
+    {
+        return $this->_data['value'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/ParameterBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/ParameterBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..31ec2076df461d2d6e2468b0b9a37449bda75b43
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/ParameterBuilder.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule3\Service\V1\Entity;
+
+class ParameterBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * Set Name.
+     *
+     * @param string $name
+     * @return \Magento\TestModule3\Service\V1\Entity\ParameterBuilder
+     */
+    public function setName($name)
+    {
+        $this->data['name'] = $name;
+        return $this;
+    }
+
+    /**
+     * Set value.
+     *
+     * @param string $value
+     * @return \Magento\TestModule3\Service\V1\Entity\ParameterBuilder
+     */
+    public function setValue($value)
+    {
+        $this->data['value'] = $value;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameter.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameter.php
new file mode 100644
index 0000000000000000000000000000000000000000..775e04a2ce5ca2e3668069fbb4e7303b06a088a7
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameter.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule3\Service\V1\Entity;
+
+class WrappedErrorParameter extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * Get field name.
+     *
+     * @return string $name
+     */
+    public function getFieldName()
+    {
+        return $this->_data['field_name'];
+    }
+
+    /**
+     * Get value.
+     *
+     * @return string $value
+     */
+    public function getValue()
+    {
+        return $this->_data['value'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameterBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameterBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..d6b3f9de2aec33064eec74f16014f2b59afd0bb8
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Entity/WrappedErrorParameterBuilder.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule3\Service\V1\Entity;
+
+class WrappedErrorParameterBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * Set field name.
+     *
+     * @param string $fieldName
+     * @return $this
+     */
+    public function setFieldName($fieldName)
+    {
+        $this->data['field_name'] = $fieldName;
+        return $this;
+    }
+
+    /**
+     * Set value.
+     *
+     * @param string $value
+     * @return $this
+     */
+    public function setValue($value)
+    {
+        $this->data['value'] = $value;
+        return $this;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php
new file mode 100644
index 0000000000000000000000000000000000000000..6410845b0516d3dde2647155a87b6137a7cfd75e
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/Error.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Implementation of a test service for error handling testing
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule3\Service\V1;
+
+use Magento\Framework\Exception\AuthorizationException;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestModule3\Service\V1\Entity\Parameter;
+use Magento\TestModule3\Service\V1\Entity\ParameterBuilder;
+
+class Error implements \Magento\TestModule3\Service\V1\ErrorInterface
+{
+    /**
+     * @var ParameterBuilder
+     */
+    protected $parameterBuilder;
+
+    /**
+     * @param ParameterBuilder $parameterBuilder
+     */
+    public function __construct(ParameterBuilder $parameterBuilder)
+    {
+        $this->parameterBuilder = $parameterBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function success()
+    {
+        return $this->parameterBuilder->setName('id')->setValue('a good id')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function resourceNotFoundException()
+    {
+        throw new NoSuchEntityException('Resource with ID "%resource_id" not found.', ['resource_id' => 'resourceY']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function serviceException()
+    {
+        throw new LocalizedException('Generic service exception %param', ['param' => 3456]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function parameterizedServiceException($parameters)
+    {
+        $details = [];
+        foreach ($parameters as $parameter) {
+            $details[$parameter->getName()] = $parameter->getValue();
+        }
+        throw new LocalizedException('Parameterized service exception', $details);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function authorizationException()
+    {
+        throw new AuthorizationException('Consumer is not authorized to access %resources', [
+            'resources'   => 'resourceN'
+        ]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function webapiException()
+    {
+        throw new \Magento\Webapi\Exception('Service not found', 5555, \Magento\Webapi\Exception::HTTP_NOT_FOUND);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function otherException()
+    {
+        throw new \Exception('Non service exception', 5678);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function returnIncompatibleDataType()
+    {
+        return "incompatibleDataType";
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function inputException($wrappedErrorParameters)
+    {
+        $exception = new InputException();
+        if ($wrappedErrorParameters) {
+            foreach ($wrappedErrorParameters as $error) {
+                $exception->addError(
+                    InputException::INVALID_FIELD_VALUE,
+                    ['fieldName' => $error->getFieldName(), 'value' => $error->getValue()]
+                );
+            }
+        }
+        throw $exception;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/ErrorInterface.php b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/ErrorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..59612a9755b750bcf8e3974b206e323e87be4bac
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/Service/V1/ErrorInterface.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Interface for a test service for error handling testing
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule3\Service\V1;
+
+use Magento\TestModule3\Service\V1\Entity\Parameter;
+
+interface ErrorInterface
+{
+    /**
+     * @return \Magento\TestModule3\Service\V1\Entity\Parameter
+     */
+    public function success();
+
+    /**
+     * @return int Status
+     */
+    public function resourceNotFoundException();
+
+    /**
+     * @return int Status
+     */
+    public function serviceException();
+
+    /**
+     * @param \Magento\TestModule3\Service\V1\Entity\Parameter[] $parameters
+     * @return int Status
+     */
+    public function parameterizedServiceException($parameters);
+
+    /**
+     * @return int Status
+     */
+    public function authorizationException();
+
+    /**
+     * @return int Status
+     */
+    public function webapiException();
+
+    /**
+     * @return int Status
+     */
+    public function otherException();
+
+    /**
+     * @return int Status
+     */
+    public function returnIncompatibleDataType();
+
+    /**
+     * @param \Magento\TestModule3\Service\V1\Entity\WrappedErrorParameter[] $wrappedErrorParameters
+     * @return int Status
+     */
+    public function inputException($wrappedErrorParameters);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModule3/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..556c098784384a38a6c7323e2b71731b959f407c
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/etc/acl.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModule3::all" title="TestModule3" sortOrder="1">
+                    <resource id="Magento_TestModule3::resource1" title="Resource1" sortOrder="20"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule3/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b26be009346343d0e43a5a7c29312d8e67e978d6
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/etc/di.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\TestModule3\Service\V1\ErrorInterface" type="Magento\TestModule3\Service\V1\Error" />
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..42ae9667a277150322d4c2a793a87c2882edeeab
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModule3" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule3/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModule3/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca7043e0c429cbcbf1b42a16e29bfdd4db6164eb
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule3/etc/webapi.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route method="GET" url="/V1/errortest/success">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="success" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/notfound">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="resourceNotFoundException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/serviceexception">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="serviceException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/errortest/parameterizedserviceexception">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="parameterizedServiceException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/unauthorized">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="authorizationException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+            <resource ref="Magento_TestModule3::resource2" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/otherException">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="otherException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/returnIncompatibleDataType">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="returnIncompatibleDataType" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/errortest/webapiException">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="webapiException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/errortest/inputException">
+        <service class="Magento\TestModule3\Service\V1\ErrorInterface" method="inputException" />
+        <resources>
+            <resource ref="Magento_TestModule3::resource1" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Model/Resource/Item.php b/dev/tests/api-functional/_files/Magento/TestModule4/Model/Resource/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..346d39bdca4b16a57bc51aee9b23f99b67143b0f
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Model/Resource/Item.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule4\Model\Resource;
+
+/**
+ * Sample resource model
+ */
+class Item extends \Magento\Framework\Model\Resource\Db\AbstractDb
+{
+    /**
+     * Initialize connection and define main table
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('dummy_item', 'dummy_item_id');
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectService.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectService.php
new file mode 100644
index 0000000000000000000000000000000000000000..9c960939015e0c93a992ce14957aa39d8d965d46
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectService.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1;
+
+use Magento\TestModule4\Service\V1\Entity\DataObjectRequest;
+use Magento\TestModule4\Service\V1\Entity\DataObjectResponseBuilder;
+use Magento\TestModule4\Service\V1\Entity\ExtensibleRequestInterface;
+use Magento\TestModule4\Service\V1\Entity\NestedDataObjectRequest;
+
+class DataObjectService implements \Magento\TestModule4\Service\V1\DataObjectServiceInterface
+{
+    /**
+     * @var DataObjectResponseBuilder
+     */
+    protected $responseBuilder;
+
+    /**
+     * @param DataObjectResponseBuilder $responseBuilder
+     */
+    public function __construct(DataObjectResponseBuilder $responseBuilder)
+    {
+        $this->responseBuilder = $responseBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getData($id)
+    {
+        return $this->responseBuilder->setEntityId($id)->setName("Test")->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function updateData($id, DataObjectRequest $request)
+    {
+        return $this->responseBuilder->setEntityId($id)->setName($request->getName())->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function nestedData($id, NestedDataObjectRequest $request)
+    {
+        return $this->responseBuilder->setEntityId($id)->setName($request->getDetails()->getName())->create();
+    }
+
+    /**
+     * Test return scalar value
+     *
+     * @param int $id
+     * @return int
+     */
+    public function scalarResponse($id)
+    {
+        return $id;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function extensibleDataObject($id, ExtensibleRequestInterface $request)
+    {
+        return $this->responseBuilder->setEntityId($id)->setName($request->getName())->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectServiceInterface.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..f189b2c9ef42a3c4d2f478c44cf0aa06eadc2097
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/DataObjectServiceInterface.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1;
+
+use Magento\TestModule4\Service\V1\Entity\DataObjectRequest;
+use Magento\TestModule4\Service\V1\Entity\NestedDataObjectRequest;
+
+interface DataObjectServiceInterface
+{
+    /**
+     * @param int $id
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectResponse
+     */
+    public function getData($id);
+
+    /**
+     * @param int $id
+     * @param \Magento\TestModule4\Service\V1\Entity\DataObjectRequest $request
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectResponse
+     */
+    public function updateData($id, DataObjectRequest $request);
+
+    /**
+     * @param int $id
+     * @param \Magento\TestModule4\Service\V1\Entity\NestedDataObjectRequest $request
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectResponse
+     */
+    public function nestedData($id, NestedDataObjectRequest $request);
+
+    /**
+     * Test return scalar value
+     *
+     * @param int $id
+     * @return int
+     */
+    public function scalarResponse($id);
+
+    /**
+     * @param int $id
+     * @param \Magento\TestModule4\Service\V1\Entity\ExtensibleRequestInterface $request
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectResponse
+     */
+    public function extensibleDataObject($id, \Magento\TestModule4\Service\V1\Entity\ExtensibleRequestInterface $request);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequest.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c3f3dff0f4fb6890b5b2ce65032c8ef25fa2957
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequest.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class DataObjectRequest extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_get('name');
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getEntityId()
+    {
+        return $this->_get('entity_id');
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequestBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequestBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3d92a6d74a3c2baa2b386889aa69b913bd53678
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectRequestBuilder.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class DataObjectRequestBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param string $name
+     * @return DataObjectRequest
+     */
+    public function setName($name)
+    {
+        return $this->_set('name', $name);
+    }
+
+    /**
+     * @param int $entityId
+     * @return DataObjectRequest
+     */
+    public function setEntityId($entityId)
+    {
+        return $this->_set('entity_id', $entityId);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponse.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..0086eda109521c4f4894204e5694e478ac8050d6
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponse.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class DataObjectResponse extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return int
+     */
+    public function getEntityId()
+    {
+        return $this->_get('entity_id');
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_get('name');
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponseBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponseBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..288c72299852709e26e36906a75eda74e935634e
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/DataObjectResponseBuilder.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class DataObjectResponseBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param int $entityId
+     * @return DataObjectResponseBuilder
+     */
+    public function setEntityId($entityId)
+    {
+        return $this->_set('entity_id', $entityId);
+    }
+
+    /**
+     * @param string $name
+     * @return DataObjectResponseBuilder
+     */
+    public function setName($name)
+    {
+        return $this->_set('name', $name);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequest.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..41f78a2ed61cc9b620b2864cce32452651b1ab35
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequest.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class ExtensibleRequest extends \Magento\Framework\Model\AbstractExtensibleModel
+    implements ExtensibleRequestInterface
+{
+    public function getName()
+    {
+        return $this->getData("name");
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd258c7af99a2d8922a5e2b92d6f50c8a7cfad11
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/ExtensibleRequestInterface.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+interface ExtensibleRequestInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**
+     * @return string
+     */
+    public function getName();
+
+    /**
+     * @return int|null
+     */
+    public function getEntityId();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequest.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c2775f006da8222eaee4035575308cd128275b7
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequest.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class NestedDataObjectRequest extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    /**
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectRequest
+     */
+    public function getDetails()
+    {
+        return $this->_get('details');
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequestBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequestBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..68e0123e75e279034a5dcdfbb1c126d048097c1d
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/Service/V1/Entity/NestedDataObjectRequestBuilder.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule4\Service\V1\Entity;
+
+class NestedDataObjectRequestBuilder extends \Magento\Framework\Api\ExtensibleObjectBuilder
+{
+    /**
+     * @param \Magento\TestModule4\Service\V1\Entity\DataObjectRequest $details
+     * @return \Magento\TestModule4\Service\V1\Entity\DataObjectRequest
+     */
+    public function setDetails(DataObjectRequest $details)
+    {
+        return $this->_set('details', $details);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModule4/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb35e81b7750b58814484a7c3edb60e747d2db75
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/etc/acl.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModule4::all" title="TestModule4" sortOrder="1">
+                    <resource id="Magento_TestModule4::resource1" title="Resource1" sortOrder="20"/>
+                    <resource id="Magento_TestModule4::resource2" title="Resource2" sortOrder="10"/>
+                    <resource id="Magento_TestModule4::resource3" title="Resource3" sortOrder="30"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule4/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d41a2955c3398e375393522fd659a7c9286ebb95
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/etc/di.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\TestModule4\Service\V1\DataObjectServiceInterface" type="Magento\TestModule4\Service\V1\DataObjectService" />
+    <preference for="Magento\TestModule4\Service\V1\Entity\ExtensibleRequestInterface" type="Magento\TestModule4\Service\V1\Entity\ExtensibleRequest" />
+    <type name="Magento\TestModule4\Service\V1\Entity\ExtensibleRequest">
+        <arguments>
+            <argument name="resource" xsi:type="object">Magento\TestModule4\Model\Resource\Item</argument>
+        </arguments>
+    </type>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f433c75e68f9ab915eae3aeea9eef076849a9c03
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModule4" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule4/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModule4/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..196aaf5ff2a06544f30372d3ccd7d597f051785a
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule4/etc/webapi.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route method="GET" url="/V1/testmodule4/:id">
+        <service class="Magento\TestModule4\Service\V1\DataObjectServiceInterface" method="getData" />
+        <resources>
+            <resource ref="Magento_TestModule4::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testmodule4/scalar/:id">
+        <service class="Magento\TestModule4\Service\V1\DataObjectServiceInterface" method="scalarResponse" />
+        <resources>
+            <resource ref="Magento_TestModule4::resource1" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmodule4/:id">
+        <service class="Magento\TestModule4\Service\V1\DataObjectServiceInterface" method="updateData" />
+        <resources>
+            <resource ref="Magento_TestModule4::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmodule4/:id/nested">
+        <service class="Magento\TestModule4\Service\V1\DataObjectServiceInterface" method="nestedData" />
+        <resources>
+            <resource ref="Magento_TestModule4::resource3" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmodule4/extensibleDataObject/:id">
+        <service class="Magento\TestModule4\Service\V1\DataObjectServiceInterface" method="extensibleDataObject" />
+        <resources>
+            <resource ref="Magento_TestModule4::resource3" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6cf3942fe2d754f9119201e3e4d58503d13ff676
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V1;
+
+use Magento\TestModule5\Service\V1\Entity\AllSoapAndRestBuilder;
+
+class AllSoapAndRest implements \Magento\TestModule5\Service\V1\AllSoapAndRestInterface
+{
+    /**
+     * @var AllSoapAndRestBuilder
+     */
+    protected $builder;
+
+    /**
+     * @param AllSoapAndRestBuilder $builder
+     */
+    public function __construct(AllSoapAndRestBuilder $builder)
+    {
+        $this->builder = $builder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($entityId)
+    {
+        return $this->builder
+            ->setEntityId($entityId)
+            ->setName('testItemName')
+            ->setIsEnabled(true)
+            ->setHasOrders(true)
+            ->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items()
+    {
+        $allSoapAndRest1 = $this->builder->setEntityId(1)->setName('testProduct1')->create();
+        $allSoapAndRest2 = $this->builder->setEntityId(2)->setName('testProduct2')->create();
+        return [$allSoapAndRest1, $allSoapAndRest2];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create(\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $item)
+    {
+        return $this->builder->populate($item)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem)
+    {
+        return $entityItem;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function nestedUpdate(
+        $parentId,
+        $entityId,
+        \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem
+    ) {
+        return $entityItem;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..de1b4472479b98ef9b4dfbba4ac986709f8a0c2c
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/AllSoapAndRestInterface.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V1;
+
+interface AllSoapAndRestInterface
+{
+    /**
+     * Retrieve an item.
+     *
+     * @param int $entityId
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+     * @throws \Magento\Webapi\Exception
+     */
+    public function item($entityId);
+
+    /**
+     * Retrieve all items.
+     *
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest[]
+     */
+    public function items();
+
+    /**
+     * Create a new item.
+     *
+     * @param \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $item
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+     */
+    public function create(\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $item);
+
+    /**
+     * Update existing item.
+     *
+     * @param \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+     */
+    public function update(\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem);
+
+    /**
+     * Update existing item.
+     *
+     * @param string $parentId
+     * @param string $entityId
+     * @param \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+     */
+    public function nestedUpdate(
+        $parentId,
+        $entityId,
+        \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest $entityItem
+    );
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..19e78efe69463cccaf0f21a64c5db0ab57d336ac
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRest.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V1\Entity;
+
+/**
+ * Some Data Object short description.
+ *
+ * Data Object long
+ * multi line description.
+ */
+class AllSoapAndRest extends \Magento\Framework\Api\AbstractExtensibleObject
+{
+    const ID = 'entity_id';
+    const NAME = 'name';
+    const ENABLED = 'enabled';
+    const HAS_ORDERS = 'orders';
+
+    /**
+     * Retrieve item ID.
+     *
+     * @return int Item ID
+     */
+    public function getEntityId()
+    {
+        return $this->_get(self::ID);
+    }
+
+    /**
+     * Retrieve item Name.
+     *
+     * @return string|null Item name
+     */
+    public function getName()
+    {
+        return $this->_get(self::NAME);
+    }
+
+    /**
+     * Check if entity is enabled
+     *
+     * @return bool
+     */
+    public function isEnabled()
+    {
+        return $this->_get(self::ENABLED);
+    }
+
+    /**
+     * Check if current entity has a property defined
+     *
+     * @return bool
+     */
+    public function hasOrders()
+    {
+        return $this->_get(self::HAS_ORDERS);
+    }
+
+    /**
+     * Method which will not be used when adding complex type field to WSDL.
+     *
+     * @param string $value
+     * @return string
+     */
+    public function getFieldExcludedFromWsdl($value)
+    {
+        return $value;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRestBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRestBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..70ed93fa515aa4a78d23a9697b719e63db533335
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/Entity/AllSoapAndRestBuilder.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V1\Entity;
+
+use Magento\Framework\Api\AbstractSimpleObjectBuilder;
+
+/**
+ * Some Data Object short description.
+ *
+ * Data Object long
+ * multi line description.
+ */
+class AllSoapAndRestBuilder extends AbstractSimpleObjectBuilder
+{
+    /**
+     * @param int $id
+     * @return AllSoapAndRestBuilder
+     */
+    public function setEntityId($id)
+    {
+        return $this->_set(AllSoapAndRest::ID, $id);
+    }
+
+    /**
+     * @param string $name
+     * @return AllSoapAndRestBuilder
+     */
+    public function setName($name)
+    {
+        return $this->_set(AllSoapAndRest::NAME, $name);
+    }
+
+    /**
+     * Set flag if entity is enabled
+     *
+     * @param bool $isEnabled
+     * @return AllSoapAndRestBuilder
+     */
+    public function setIsEnabled($isEnabled)
+    {
+        return $this->_set(AllSoapAndRest::ENABLED, $isEnabled);
+    }
+
+    /**
+     * Set flag if entity has orders
+     *
+     * @param bool $hasOrders
+     * @return AllSoapAndRestBuilder
+     */
+    public function setHasOrders($hasOrders)
+    {
+        return $this->_set(AllSoapAndRest::HAS_ORDERS, $hasOrders);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideService.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideService.php
new file mode 100644
index 0000000000000000000000000000000000000000..d5fb874d457bce5a61aac253687cee80e3099a91
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideService.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule5\Service\V1;
+
+use Magento\TestModule5\Service\V1\Entity\AllSoapAndRestBuilder;
+
+class OverrideService implements OverrideServiceInterface
+{
+    /**
+     * @var AllSoapAndRestBuilder
+     */
+    protected $builder;
+
+    /**
+     * @param AllSoapAndRestBuilder $builder
+     */
+    public function __construct(AllSoapAndRestBuilder $builder)
+    {
+        $this->builder = $builder;
+    }
+    /**
+     * {@inheritdoc}
+     */
+    public function scalarUpdate($entityId, $name, $hasOrders)
+    {
+        return $this->builder
+            ->setEntityId($entityId)
+            ->setName($name)
+            ->setHasOrders($hasOrders)
+            ->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideServiceInterface.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideServiceInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..f8ce591980b5c2914d51e54f473882b6a589e404
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V1/OverrideServiceInterface.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModule5\Service\V1;
+
+interface OverrideServiceInterface
+{
+    /**
+     * Update existing item.
+     *
+     * @param string $entityId
+     * @param string $name
+     * @param bool $orders
+     * @return \Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+     */
+    public function scalarUpdate($entityId, $name, $orders);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4b006e8feadf62720ab0a0b950980b12909e40a
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRest.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V2;
+
+use Magento\TestModule5\Service\V2\Entity\AllSoapAndRest as AllSoapAndRestEntity;
+use Magento\TestModule5\Service\V2\Entity\AllSoapAndRestBuilder;
+
+class AllSoapAndRest implements AllSoapAndRestInterface
+{
+    /**
+     * @var AllSoapAndRestBuilder
+     */
+    protected $builder;
+
+    /**
+     * @param AllSoapAndRestBuilder $builder
+     */
+    public function __construct(AllSoapAndRestBuilder $builder)
+    {
+        $this->builder = $builder;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function item($id)
+    {
+        return $this->builder->setPrice(1)->setId($id)->setName('testItemName')->create();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function items()
+    {
+        $allSoapAndRest1 = $this->builder->setPrice(1)->setId(1)->setName('testProduct1')->create();
+        $allSoapAndRest2 = $this->builder->setPrice(1)->setId(2)->setName('testProduct2')->create();
+        return [$allSoapAndRest1, $allSoapAndRest2];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function create(\Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item)
+    {
+        return $this->builder->populate($item)->create();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function update(\Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item)
+    {
+        $item->setName('Updated' . $item->getName());
+        return $this->builder->populate($item)->create();
+    }
+
+    /**
+     * @param string $id
+     * @return AllSoapAndRestEntity
+     * @throws \Magento\Webapi\Exception
+     */
+    public function delete($id)
+    {
+        return $this->builder->setPrice(1)->setId($id)->setName('testItemName')->create();
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..dce9a15f0f5dc720e97996e8c470f98e19bddf8b
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/AllSoapAndRestInterface.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V2;
+
+interface AllSoapAndRestInterface
+{
+    /**
+     * Retrieve existing item.
+     *
+     * @param int $id
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest
+     * @throws \Magento\Webapi\Exception
+     */
+    public function item($id);
+
+    /**
+     * Retrieve a list of all existing items.
+     *
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest[]
+     */
+    public function items();
+
+    /**
+     * Add new item.
+     *
+     * @param \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest
+     */
+    public function create(\Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item);
+
+    /**
+     * Update one item.
+     *
+     * @param \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest
+     */
+    public function update(\Magento\TestModule5\Service\V2\Entity\AllSoapAndRest $item);
+
+    /**
+     * Delete existing item.
+     *
+     * @param string $id
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRest
+     */
+    public function delete($id);
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..35e3674b679ab6623ed7f417738dd3010297b994
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRest.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V2\Entity;
+
+class AllSoapAndRest extends \Magento\TestModule5\Service\V2\AllSoapAndRest
+{
+    const PRICE = 'price';
+
+    /**
+     * @return int
+     */
+    public function getPrice()
+    {
+        return $this->_get(self::PRICE);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRestBuilder.php b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRestBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..d68589484b322c64b7ddb3147e3519e8ab03646e
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/Service/V2/Entity/AllSoapAndRestBuilder.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModule5\Service\V2\Entity;
+
+use Magento\TestModule5\Service\V1\Entity;
+
+class AllSoapAndRestBuilder extends \Magento\TestModule5\Service\V1\Entity\AllSoapAndRestBuilder
+{
+    const PRICE = 'price';
+
+    /**
+     * @param int $price
+     * @return \Magento\TestModule5\Service\V2\Entity\AllSoapAndRestBuilder
+     */
+    public function setPrice($price)
+    {
+        return $this->_set(self::PRICE, $price);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModule5/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebad51bd78d996e7fecd8ca070bacb434028a93b
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/etc/acl.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModule5::all" title="TestModule5" sortOrder="1">
+                    <resource id="Magento_TestModule5::resource1" title="Resource1" sortOrder="20"/>
+                    <resource id="Magento_TestModule5::resource2" title="Resource2" sortOrder="10"/>
+                    <resource id="Magento_TestModule5::resource3" title="Resource3" sortOrder="30"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule5/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..13e121a2d7220be0c26b7785e033e496b0c47610
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/etc/di.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" type="Magento\TestModule5\Service\V1\AllSoapAndRest" />
+    <preference for="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" type="Magento\TestModule5\Service\V2\AllSoapAndRest" />
+    <preference for="Magento\TestModule5\Service\V1\OverrideServiceInterface" type="Magento\TestModule5\Service\V1\OverrideService" />
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..801468fd880a1697f3d4644135cf8dea87da8568
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModule5" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModule5/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModule5/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..38cbd15afb17892b91493662cb015dce20c69937
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModule5/etc/webapi.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+    <route method="GET" url="/V1/TestModule5/:entityId">
+        <service class="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/TestModule5">
+        <service class="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/TestModule5">
+        <service class="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" method="create" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource3" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V1/TestModule5/:entityId">
+        <service class="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" method="update" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V1/TestModule5/:parentId/nestedResource/:entityId">
+        <service class="Magento\TestModule5\Service\V1\AllSoapAndRestInterface" method="nestedUpdate" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V1/TestModule5/OverrideService/:parentId/nestedResource/:entityId">
+        <service class="Magento\TestModule5\Service\V1\OverrideServiceInterface" method="scalarUpdate" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="GET" url="/V2/TestModule5/:id">
+        <service class="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V2/TestModule5">
+        <service class="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V2/TestModule5">
+        <service class="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" method="create" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource3" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V2/TestModule5/:id">
+        <service class="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" method="update" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+            <resource ref="Magento_TestModule5::resource2" />
+        </resources>
+    </route>
+    <route method="DELETE" url="/V2/TestModule5/:id">
+        <service class="Magento\TestModule5\Service\V2\AllSoapAndRestInterface" method="delete" />
+        <resources>
+            <resource ref="Magento_TestModule5::resource1" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/AllSoapAndRestInterface.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/AllSoapAndRestInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..baa4ab49f376be3b933997ec09a715be8a621992
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/AllSoapAndRestInterface.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Api;
+
+interface AllSoapAndRestInterface
+{
+    /**
+     * @param int $itemId
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function item($itemId);
+
+    /**
+     * @param string $name
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function create($name);
+
+    /**
+     * @param \Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function update(\Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem);
+
+    /**
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface[]
+     */
+    public function items();
+
+    /**
+     * @param string $name
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function testOptionalParam($name = null);
+
+    /**
+     * @param \Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function itemAnyType(\Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem);
+
+    /**
+     * @return \Magento\TestModuleMSC\Api\Data\ItemInterface
+     */
+    public function getPreconfiguredItem();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeDataObjectInterface.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeDataObjectInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0710ee62a85158a9494336ba209504860e513281
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeDataObjectInterface.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Api\Data;
+
+interface CustomAttributeDataObjectInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    const NAME = 'name';
+
+    /**
+     * @return string
+     */
+    public function getName();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeNestedDataObjectInterface.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeNestedDataObjectInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c5b634bd15e9b82dd078217f044c06b355add1a
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/CustomAttributeNestedDataObjectInterface.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Api\Data;
+
+interface CustomAttributeNestedDataObjectInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**
+     * @return string
+     */
+    public function getName();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/ItemInterface.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/ItemInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..65595bafe836436811fb65b4bf8c1d9b14d8fe2b
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Api/Data/ItemInterface.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Api\Data;
+
+interface ItemInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+{
+    /**
+     * @return int
+     */
+    public function getItemId();
+
+    /**
+     * @return string
+     */
+    public function getName();
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/AllSoapAndRest.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/AllSoapAndRest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cca810f6ca4d47b3e73bbae34e16b5d8c225a07a
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/AllSoapAndRest.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model;
+
+use Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectDataBuilder;
+use Magento\TestModuleMSC\Api\Data\ItemDataBuilder;
+
+class AllSoapAndRest implements \Magento\TestModuleMSC\Api\AllSoapAndRestInterface
+{
+    /**
+     * @var ItemDataBuilder
+     */
+    protected $itemDataBuilder;
+
+    /**
+     * @var CustomAttributeDataObjectDataBuilder
+     */
+    protected $customAttributeDataObjectDataBuilder;
+
+    /**
+     * @param ItemDataBuilder $itemDataBuilder
+     * @param CustomAttributeDataObjectDataBuilder $customAttributeNestedDataObjectBuilder
+     */
+    public function __construct(
+        ItemDataBuilder $itemDataBuilder,
+        CustomAttributeDataObjectDataBuilder $customAttributeNestedDataObjectBuilder
+    ) {
+        $this->itemDataBuilder = $itemDataBuilder;
+        $this->customAttributeDataObjectDataBuilder = $customAttributeNestedDataObjectBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function item($itemId)
+    {
+        return $this->itemDataBuilder->setItemId($itemId)->setName('testProduct1')->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function items()
+    {
+        $result1 = $this->itemDataBuilder->setItemId(1)->setName('testProduct1')->create();
+        $result2 = $this->itemDataBuilder->setItemId(2)->setName('testProduct2')->create();
+
+        return [$result1, $result2];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create($name)
+    {
+        return $this->itemDataBuilder->setItemId(rand())->setName($name)->create();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update(\Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem)
+    {
+        return $this->itemDataBuilder->setItemId($entityItem->getItemId())
+            ->setName('Updated' . $entityItem->getName())
+            ->create();
+    }
+
+    public function testOptionalParam($name = null)
+    {
+        if (is_null($name)) {
+            return $this->itemDataBuilder->setItemId(3)->setName('No Name')->create();
+        } else {
+            return $this->itemDataBuilder->setItemId(3)->setName($name)->create();
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function itemAnyType(\Magento\TestModuleMSC\Api\Data\ItemInterface $entityItem)
+    {
+        return $entityItem;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPreconfiguredItem()
+    {
+        $customAttributeDataObject = $this->customAttributeDataObjectDataBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemDataBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        return $item;
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeDataObject.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeDataObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..dc3a1c1a17ece2d251d28e1fb18984174786bd41
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeDataObject.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model\Data;
+
+use Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface;
+
+class CustomAttributeDataObject extends \Magento\Framework\Api\AbstractExtensibleObject
+    implements CustomAttributeDataObjectInterface
+{
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeNestedDataObject.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeNestedDataObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..9ea73d87acee50649757bb3622933b42aeefa1cd
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/CustomAttributeNestedDataObject.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model\Data;
+
+use Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectInterface;
+
+class CustomAttributeNestedDataObject extends \Magento\Framework\Model\AbstractExtensibleModel
+    implements CustomAttributeNestedDataObjectInterface
+{
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadata.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadata.php
new file mode 100644
index 0000000000000000000000000000000000000000..2977a6e50691abf1b2c8f4f9996d0e1c340eef98
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadata.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model\Data\Eav;
+
+use Magento\Framework\Api\AbstractExtensibleObject;
+use Magento\Framework\Api\MetadataObjectInterface;
+
+/**
+ * Class AttributeMetadata
+ */
+class AttributeMetadata extends AbstractExtensibleObject implements MetadataObjectInterface
+{
+    /**#@+
+     * Constants used as keys into $_data
+     */
+    const ATTRIBUTE_ID = 'attribute_id';
+
+    const ATTRIBUTE_CODE = 'attribute_code';
+    /**#@-*/
+
+    /**
+     * Retrieve id of the attribute.
+     *
+     * @return string|null
+     */
+    public function getAttributeId()
+    {
+        return $this->_get(self::ATTRIBUTE_ID);
+    }
+
+    /**
+     * Retrieve code of the attribute.
+     *
+     * @return string|null
+     */
+    public function getAttributeCode()
+    {
+        return $this->_get(self::ATTRIBUTE_CODE);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadataBuilder.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadataBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..d037b299cd059cbf378598d17ecd0d31dd09c628
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Eav/AttributeMetadataBuilder.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model\Data\Eav;
+
+use Magento\Framework\Api\AttributeMetadataBuilderInterface;
+use Magento\Framework\Api\ExtensibleObjectBuilder;
+
+/**
+ * Class AttributeMetadataBuilder
+ */
+class AttributeMetadataBuilder extends ExtensibleObjectBuilder implements AttributeMetadataBuilderInterface
+{
+    /**
+     * Set attribute id
+     *
+     * @param  int $attributeId
+     * @return $this
+     */
+    public function setAttributeId($attributeId)
+    {
+        return $this->_set(AttributeMetadata::ATTRIBUTE_ID, $attributeId);
+    }
+
+    /**
+     * Set attribute code
+     *
+     * @param  string $attributeCode
+     * @return $this
+     */
+    public function setAttributeCode($attributeCode)
+    {
+        return $this->_set(AttributeMetadata::ATTRIBUTE_CODE, $attributeCode);
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Item.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..5593ffcffb412548e6b0796000e661fccd51c3b4
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Data/Item.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestModuleMSC\Model\Data;
+
+use Magento\TestModuleMSC\Api\Data\ItemInterface;
+
+class Item extends \Magento\Framework\Model\AbstractExtensibleModel
+    implements ItemInterface
+{
+    /**
+     * @return int
+     */
+    public function getItemId()
+    {
+        return $this->_data['item_id'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_data['name'];
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Resource/Item.php b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Resource/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1236934e35a504bbb3a07d021d65492693eb6a1
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/Model/Resource/Item.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestModuleMSC\Model\Resource;
+
+/**
+ * Sample resource model
+ */
+class Item extends \Magento\Framework\Model\Resource\Db\AbstractDb
+{
+    /**
+     * Initialize connection and define main table
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_init('dummy_item', 'dummy_item_id');
+    }
+}
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/acl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..923334c57ddd2347ccc53c4cb50db3ab5c1b77da
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/acl.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Acl/etc/acl.xsd">
+    <acl>
+        <resources>
+            <resource id="Magento_Adminhtml::admin">
+                <resource id="Magento_TestModuleMSC::all" title="TestModuleMSC" sortOrder="1">
+                    <resource id="Magento_TestModuleMSC::resource1" title="Resource1" sortOrder="20"/>
+                    <resource id="Magento_TestModuleMSC::resource2" title="Resource2" sortOrder="10"/>
+                    <resource id="Magento_TestModuleMSC::resource3" title="Resource3" sortOrder="30"/>
+                </resource>
+            </resource>
+        </resources>
+    </acl>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8fed3f6421cfb9030ebae2728c77e4bf1db5861e
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/data_object.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/data_object.xsd">
+    <custom_attributes for="Magento\TestModuleMSC\Api\Data\ItemInterface">
+        <attribute code="custom_attribute_data_object" type="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface" />
+        <attribute code="custom_attribute_string" type="string" />
+    </custom_attributes>
+    <custom_attributes for="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface">
+        <attribute code="custom_attribute_nested" type="Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectInterface" />
+        <attribute code="custom_attribute_int" type="int" />
+    </custom_attributes>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml
new file mode 100644
index 0000000000000000000000000000000000000000..62788df693dbe8215ad23ac2f8e698f0b3b6ef3a
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+
+    <preference for="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" type="Magento\TestModuleMSC\Model\AllSoapAndRest" />
+
+    <preference for="Magento\TestModuleMSC\Api\Data\ItemInterface" type="Magento\TestModuleMSC\Model\Data\Item" />
+    <preference for="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface" type="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject" />
+    <preference for="Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectInterface" type="Magento\TestModuleMSC\Model\Data\CustomAttributeNestedDataObject" />
+
+    <virtualType name="Magento\TestModuleMSC\Service\Config\TestModuleMSCMetadataConfig" type="Magento\Framework\Api\Config\MetadataConfig">
+        <arguments>
+            <argument name="attributeMetadataBuilder" xsi:type="object">Magento\TestModuleMSC\Model\Data\Eav\AttributeMetadataBuilder</argument>
+            <argument name="dataObjectClassName" xsi:type="string">Magento\TestModuleMSC\Model\Data\Item</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\TestModuleMSC\Model\Data\Item">
+        <arguments>
+            <argument name="resource" xsi:type="object">Magento\TestModuleMSC\Model\Resource\Item</argument>
+            <argument name="metadataService" xsi:type="object">Magento\TestModuleMSC\Service\Config\TestModuleMSCMetadataConfig</argument>
+        </arguments>
+    </type>
+    <type name="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject">
+        <arguments>
+            <argument name="resource" xsi:type="object">Magento\TestModuleMSC\Model\Resource\Item</argument>
+        </arguments>
+    </type>
+    <type name="Magento\TestModuleMSC\Model\Data\CustomAttributeNestedDataObject">
+        <arguments>
+            <argument name="resource" xsi:type="object">Magento\TestModuleMSC\Model\Resource\Item</argument>
+        </arguments>
+    </type>
+
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml
new file mode 100644
index 0000000000000000000000000000000000000000..554ab6d9d9143f03d394987815140ff52f9c8e11
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/module.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_TestModuleMSC" schema_version="1.0"/>
+</config>
diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/webapi.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ed721a73e8e884195f5c4aaba36b6118c3b91089
--- /dev/null
+++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/webapi.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
+
+    <route method="GET" url="/V1/testmoduleMSC/overwritten">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+        </resources>
+        <data>
+            <parameter name="itemId" force="true">-55</parameter>
+        </data>
+    </route>
+
+    <route method="POST" url="/V1/testmoduleMSC/testOptionalParam">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="testOptionalParam" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+        </resources>
+        <data>
+            <parameter name="name">Default Name</parameter>
+        </data>
+    </route>
+
+    <route method="GET" url="/V1/testmoduleMSC/:itemId">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="item" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testmoduleMSC">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="items" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmoduleMSC">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="create" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource3" />
+        </resources>
+    </route>
+    <route method="PUT" url="/V1/testmoduleMSC/:itemId">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="update" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+            <resource ref="Magento_TestModuleMSC::resource2" />
+        </resources>
+    </route>
+    <route method="POST" url="/V1/testmoduleMSC/itemAnyType">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="itemAnyType" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+            <resource ref="Magento_TestModuleMSC::resource2" />
+        </resources>
+    </route>
+    <route method="GET" url="/V1/testmoduleMSC/itemPreconfigured">
+        <service class="Magento\TestModuleMSC\Api\AllSoapAndRestInterface" method="getPreconfiguredItem" />
+        <resources>
+            <resource ref="Magento_TestModuleMSC::resource1" />
+            <resource ref="Magento_TestModuleMSC::resource2" />
+        </resources>
+    </route>
+</routes>
diff --git a/dev/tests/api-functional/config/install-config-mysql.php.dist b/dev/tests/api-functional/config/install-config-mysql.php.dist
new file mode 100644
index 0000000000000000000000000000000000000000..85665d34d61615880847566e595d3dade4dafd3b
--- /dev/null
+++ b/dev/tests/api-functional/config/install-config-mysql.php.dist
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Magento console installer options for Web API functional tests. Are used in functional tests bootstrap.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+return [
+    'language'                     => 'en_US',
+    'timezone'                     => 'America/Los_Angeles',
+    'currency'                     => 'USD',
+    'db_host'                      => 'localhost',
+    'db_name'                      => 'magento_functional_tests',
+    'db_user'                      => 'root',
+    'db_pass'                      => '',
+    'backend_frontname'            => 'backend',
+    'base_url'                     => 'http://localhost/',
+    'use_secure'                   => '0',
+    'use_rewrites'                 => '0',
+    'admin_lastname'               => 'Admin',
+    'admin_firstname'              => 'Admin',
+    'admin_email'                  => 'admin@example.com',
+    'admin_username'               => 'admin',
+    'admin_password'               => '123123q',
+    'admin_use_security_key'       => '0',
+    /* PayPal has limitation for order number - 20 characters. 10 digits prefix + 8 digits number is good enough */
+    'sales_order_increment_prefix' => time(),
+    'session_save'                 => 'db',
+    'cleanup_database'             => true,
+];
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php
new file mode 100644
index 0000000000000000000000000000000000000000..6bc41d3a3f41e0e0e3fa1f35b87357d224236a54
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Annotation/ApiDataFixture.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Implementation of the magentoApiDataFixture DocBlock annotation.
+ *
+ * The difference of magentoApiDataFixture from magentoDataFixture is
+ * that no transactions should be used for API data fixtures.
+ * Otherwise fixture data will not be accessible to Web API functional tests.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\Annotation;
+
+class ApiDataFixture
+{
+    /**
+     * @var string
+     */
+    protected $_fixtureBaseDir;
+
+    /**
+     * Fixtures that have been applied
+     *
+     * @var array
+     */
+    private $_appliedFixtures = [];
+
+    /**
+     * Constructor
+     *
+     * @param string $fixtureBaseDir
+     * @throws \Magento\Framework\Exception
+     */
+    public function __construct($fixtureBaseDir)
+    {
+        if (!is_dir($fixtureBaseDir)) {
+            throw new \Magento\Framework\Exception("Fixture base directory '{$fixtureBaseDir}' does not exist.");
+        }
+        $this->_fixtureBaseDir = realpath($fixtureBaseDir);
+    }
+
+    /**
+     * Handler for 'startTest' event
+     *
+     * @param \PHPUnit_Framework_TestCase $test
+     */
+    public function startTest(\PHPUnit_Framework_TestCase $test)
+    {
+        /** Apply method level fixtures if thy are available, apply class level fixtures otherwise */
+        $this->_applyFixtures($this->_getFixtures('method', $test) ?: $this->_getFixtures('class', $test));
+    }
+
+    /**
+     * Handler for 'endTest' event
+     */
+    public function endTest()
+    {
+        $this->_revertFixtures();
+    }
+
+    /**
+     * Retrieve fixtures from annotation
+     *
+     * @param string $scope 'class' or 'method'
+     * @param \PHPUnit_Framework_TestCase $test
+     * @return array
+     * @throws \Magento\Framework\Exception
+     */
+    protected function _getFixtures($scope, \PHPUnit_Framework_TestCase $test)
+    {
+        $annotations = $test->getAnnotations();
+        $result = [];
+        if (!empty($annotations[$scope]['magentoApiDataFixture'])) {
+            foreach ($annotations[$scope]['magentoApiDataFixture'] as $fixture) {
+                if (strpos($fixture, '\\') !== false) {
+                    // usage of a single directory separator symbol streamlines search across the source code
+                    throw new \Magento\Framework\Exception('Directory separator "\\" is prohibited in fixture declaration.');
+                }
+                $fixtureMethod = [get_class($test), $fixture];
+                if (is_callable($fixtureMethod)) {
+                    $result[] = $fixtureMethod;
+                } else {
+                    $result[] = $this->_fixtureBaseDir . '/' . $fixture;
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * Execute single fixture script
+     *
+     * @param string|array $fixture
+     */
+    protected function _applyOneFixture($fixture)
+    {
+        try {
+            if (is_callable($fixture)) {
+                call_user_func($fixture);
+            } else {
+                require $fixture;
+            }
+        } catch (\Exception $e) {
+            echo 'Exception occurred when running the '
+            . (is_array($fixture) || is_scalar($fixture) ? json_encode($fixture) : 'callback')
+            . ' fixture: ', PHP_EOL, $e;
+        }
+        $this->_appliedFixtures[] = $fixture;
+    }
+
+    /**
+     * Execute fixture scripts if any
+     *
+     * @param array $fixtures
+     * @throws \Magento\Framework\Exception
+     */
+    protected function _applyFixtures(array $fixtures)
+    {
+        /* Execute fixture scripts */
+        foreach ($fixtures as $oneFixture) {
+            /* Skip already applied fixtures */
+            if (!in_array($oneFixture, $this->_appliedFixtures, true)) {
+                $this->_applyOneFixture($oneFixture);
+            }
+        }
+    }
+
+    /**
+     * Revert changes done by fixtures
+     */
+    protected function _revertFixtures()
+    {
+        foreach ($this->_appliedFixtures as $fixture) {
+            if (is_callable($fixture)) {
+                $fixture[1] .= 'Rollback';
+                if (is_callable($fixture)) {
+                    $this->_applyOneFixture($fixture);
+                }
+            } else {
+                $fileInfo = pathinfo($fixture);
+                $extension = '';
+                if (isset($fileInfo['extension'])) {
+                    $extension = '.' . $fileInfo['extension'];
+                }
+                $rollbackScript = $fileInfo['dirname'] . '/' . $fileInfo['filename'] . '_rollback' . $extension;
+                if (file_exists($rollbackScript)) {
+                    $this->_applyOneFixture($rollbackScript);
+                }
+            }
+        }
+        $this->_appliedFixtures = [];
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..05d33b6bb9fb29ef25a68f63d898f3e6ab30d786
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php
@@ -0,0 +1,200 @@
+<?php
+/**
+ * Helper class for generating OAuth related credentials
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\Authentication;
+
+use Magento\TestFramework\Authentication\Rest\OauthClient;
+use Magento\TestFramework\Helper\Bootstrap;
+use OAuth\Common\Consumer\Credentials;
+use Zend\Stdlib\Exception\LogicException;
+
+class OauthHelper
+{
+    /** @var array */
+    protected static $_apiCredentials;
+
+    /**
+     * Generate authentication credentials
+     * @param string $date consumer creation date
+     * @return array
+     * <pre>
+     * array (
+     *   'key' => 'ajdsjashgdkahsdlkjasldkjals', //consumer key
+     *   'secret' => 'alsjdlaskjdlaksjdlasjkdlas', //consumer secret
+     *   'verifier' => 'oiudioqueoiquweoiqwueoqwuii'
+     *   'consumer' => $consumer, // retrieved consumer Model
+     *   'token' => $token // retrieved token Model
+     *   );
+     * </pre>
+     */
+    public static function getConsumerCredentials($date = null)
+    {
+        $integration = self::_createIntegration('all');
+        $objectManager = Bootstrap::getObjectManager();
+        /** @var $oauthService \Magento\Integration\Service\V1\Oauth */
+        $oauthService = $objectManager->get('Magento\Integration\Service\V1\Oauth');
+        $consumer = $oauthService->loadConsumer($integration->getConsumerId());
+        $url = TESTS_BASE_URL;
+        $consumer->setCallbackUrl($url);
+        $consumer->setRejectedCallbackUrl($url);
+        if (!is_null($date)) {
+            $consumer->setCreatedAt($date);
+        }
+        $consumer->save();
+        $token = $objectManager->create('Magento\Integration\Model\Oauth\Token');
+        $verifier = $token->createVerifierToken($consumer->getId())->getVerifier();
+
+        return [
+            'key' => $consumer->getKey(),
+            'secret' => $consumer->getSecret(),
+            'verifier' => $verifier,
+            'consumer' => $consumer,
+            'token' => $token
+        ];
+    }
+
+    /**
+     * Create an access token to associated to a consumer to access APIs. No resources are available to this consumer.
+     *
+     * @return array comprising of token  key and secret
+     * <pre>
+     * array (
+     *   'key' => 'ajdsjashgdkahsdlkjasldkjals', //token key
+     *   'secret' => 'alsjdlaskjdlaksjdlasjkdlas', //token secret
+     *   'oauth_client' => $oauthClient // OauthClient instance used to fetch the access token
+     *   );
+     * </pre>
+     */
+    public static function getAccessToken()
+    {
+        $consumerCredentials = self::getConsumerCredentials();
+        $credentials = new Credentials($consumerCredentials['key'], $consumerCredentials['secret'], TESTS_BASE_URL);
+        $oAuthClient = new OauthClient($credentials);
+        $requestToken = $oAuthClient->requestRequestToken();
+        $accessToken = $oAuthClient->requestAccessToken(
+            $requestToken->getRequestToken(),
+            $consumerCredentials['verifier'],
+            $requestToken->getRequestTokenSecret()
+        );
+
+        /** TODO: Reconsider return format. It is not aligned with method name. */
+        return [
+            'key' => $accessToken->getAccessToken(),
+            'secret' => $accessToken->getAccessTokenSecret(),
+            'oauth_client' => $oAuthClient
+        ];
+    }
+
+    /**
+     * Create an access token, tied to integration which has permissions to all API resources in the system.
+     *
+     * @param array $resources list of resources to grant to the integration
+     * @return array
+     * <pre>
+     * array (
+     *   'key' => 'ajdsjashgdkahsdlkjasldkjals', //token key
+     *   'secret' => 'alsjdlaskjdlaksjdlasjkdlas', //token secret
+     *   'oauth_client' => $oauthClient // OauthClient instance used to fetch the access token
+     *   'integration' => $integration // Integration instance associated with access token
+     *   );
+     * </pre>
+     * @throws LogicException
+     */
+    public static function getApiAccessCredentials($resources = null)
+    {
+        if (!self::$_apiCredentials) {
+            $integration = self::_createIntegration($resources);
+            $objectManager = Bootstrap::getObjectManager();
+            /** @var \Magento\Integration\Service\V1\Oauth $oauthService */
+            $oauthService = $objectManager->get('Magento\Integration\Service\V1\Oauth');
+            $oauthService->createAccessToken($integration->getConsumerId());
+            $accessToken = $oauthService->getAccessToken($integration->getConsumerId());
+            if (!$accessToken) {
+                throw new LogicException('Access token was not created.');
+            }
+            $consumer = $oauthService->loadConsumer($integration->getConsumerId());
+            $credentials = new Credentials($consumer->getKey(), $consumer->getSecret(), TESTS_BASE_URL);
+            /** @var $oAuthClient OauthClient */
+            $oAuthClient = new OauthClient($credentials);
+
+            self::$_apiCredentials = [
+                'key' => $accessToken->getToken(),
+                'secret' => $accessToken->getSecret(),
+                'oauth_client' => $oAuthClient,
+                'integration' => $integration,
+            ];
+        }
+        return self::$_apiCredentials;
+    }
+
+    /**
+     * Forget API access credentials.
+     */
+    public static function clearApiAccessCredentials()
+    {
+        self::$_apiCredentials = false;
+    }
+
+    /**
+     * Remove fs element with nested elements.
+     *
+     * @param string $dir
+     * @param bool   $doSaveRoot
+     */
+    protected static function _rmRecursive($dir, $doSaveRoot = false)
+    {
+        if (is_dir($dir)) {
+            foreach (glob($dir . '/*') as $object) {
+                if (is_dir($object)) {
+                    self::_rmRecursive($object);
+                } else {
+                    unlink($object);
+                }
+            }
+            if (!$doSaveRoot) {
+                rmdir($dir);
+            }
+        } else {
+            unlink($dir);
+        }
+    }
+
+    /**
+     * Create integration instance.
+     *
+     * @param array $resources
+     * @return \Magento\Integration\Model\Integration
+     * @throws \Zend\Stdlib\Exception\LogicException
+     */
+    protected static function _createIntegration($resources)
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        /** @var $integrationService \Magento\Integration\Service\V1\IntegrationInterface */
+        $integrationService = $objectManager->get('Magento\Integration\Service\V1\IntegrationInterface');
+
+        $params = ['name' => 'Integration' . microtime()];
+
+        if ($resources === null || $resources == 'all') {
+            $params['all_resources'] = true;
+        } else {
+            $params['resource'] = $resources;
+        }
+        $integration = $integrationService->create($params);
+        $integration->setStatus(\Magento\Integration\Model\Integration::STATUS_ACTIVE)->save();
+
+        /** Magento cache must be cleared to activate just created ACL role. */
+        $varPath = realpath('../../../var');
+        if (!$varPath) {
+            throw new LogicException("Magento cache cannot be cleared after new ACL role creation.");
+        } else {
+            $cachePath = $varPath . '/cache';
+            if (is_dir($cachePath)) {
+                self::_rmRecursive($cachePath, true);
+            }
+        }
+        return $integration;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php
new file mode 100644
index 0000000000000000000000000000000000000000..021e836e0f37ccef541c018673ee37d4e3f9ace9
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient.php
@@ -0,0 +1,271 @@
+<?php
+/**
+ * oAuth client for Magento REST API.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\Authentication\Rest;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use OAuth\Common\Consumer\Credentials;
+use OAuth\Common\Http\Client\ClientInterface;
+use OAuth\Common\Http\Exception\TokenResponseException;
+use OAuth\Common\Http\Uri\Uri;
+use OAuth\Common\Http\Uri\UriInterface;
+use OAuth\Common\Storage\TokenStorageInterface;
+use OAuth\OAuth1\Service\AbstractService;
+use OAuth\OAuth1\Signature\SignatureInterface;
+use OAuth\OAuth1\Token\StdOAuth1Token;
+use OAuth\OAuth1\Token\TokenInterface;
+
+class OauthClient extends AbstractService
+{
+    /** @var string|null */
+    protected $_oauthVerifier = null;
+
+    public function __construct(
+        Credentials $credentials,
+        ClientInterface $httpClient = null,
+        TokenStorageInterface $storage = null,
+        SignatureInterface $signature = null,
+        UriInterface $baseApiUri = null
+    ) {
+        if (!isset($httpClient)) {
+            $httpClient = new \OAuth\Common\Http\Client\StreamClient();
+        }
+        if (!isset($storage)) {
+            $storage = new \OAuth\Common\Storage\Session();
+        }
+        if (!isset($signature)) {
+            $signature = new \Magento\TestFramework\Authentication\Rest\OauthClient\Signature($credentials);
+        }
+        parent::__construct($credentials, $httpClient, $storage, $signature, $baseApiUri);
+    }
+
+    /**
+     * @return UriInterface
+     */
+    public function getRequestTokenEndpoint()
+    {
+        return new Uri(TESTS_BASE_URL . '/oauth/token/request');
+    }
+
+    /**
+     * Returns the authorization API endpoint.
+     *
+     * @return UriInterface
+     */
+    public function getAuthorizationEndpoint()
+    {
+        throw new \OAuth\Common\Exception\Exception(
+            'Magento REST API is 2-legged. Current operation is not available.'
+        );
+    }
+
+    /**
+     * Returns the access token API endpoint.
+     *
+     * @return UriInterface
+     */
+    public function getAccessTokenEndpoint()
+    {
+        return new Uri(TESTS_BASE_URL . '/oauth/token/access');
+    }
+
+    /**
+     * Returns the TestModule1 Rest API endpoint.
+     *
+     * @return UriInterface
+     */
+    public function getTestApiEndpoint()
+    {
+        $defaultStoreCode = Bootstrap::getObjectManager()->get('Magento\Store\Model\StoreManagerInterface')
+            ->getStore()->getCode();
+        return new Uri(TESTS_BASE_URL . '/rest/' . $defaultStoreCode . '/V1/testmodule1');
+    }
+
+    /**
+     * Parses the access token response and returns a TokenInterface.
+     *
+     * @return TokenInterface
+     * @param string $responseBody
+     */
+    protected function parseAccessTokenResponse($responseBody)
+    {
+        return $this->_parseToken($responseBody);
+    }
+
+    /**
+     * Parses the request token response and returns a TokenInterface.
+     *
+     * @return TokenInterface
+     * @param string $responseBody
+     * @throws TokenResponseException
+     */
+    protected function parseRequestTokenResponse($responseBody)
+    {
+        $data = $this->_parseResponseBody($responseBody);
+        if (isset($data['oauth_verifier'])) {
+            $this->_oauthVerifier = $data['oauth_verifier'];
+        }
+        return $this->_parseToken($responseBody);
+    }
+
+    /**
+     * Parse response body and create oAuth token object based on parameters provided.
+     *
+     * @param string $responseBody
+     * @return StdOAuth1Token
+     * @throws TokenResponseException
+     */
+    protected function _parseToken($responseBody)
+    {
+        $data = $this->_parseResponseBody($responseBody);
+        $token = new StdOAuth1Token();
+        $token->setRequestToken($data['oauth_token']);
+        $token->setRequestTokenSecret($data['oauth_token_secret']);
+        $token->setAccessToken($data['oauth_token']);
+        $token->setAccessTokenSecret($data['oauth_token_secret']);
+        $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES);
+        unset($data['oauth_token'], $data['oauth_token_secret']);
+        $token->setExtraParams($data);
+        return $token;
+    }
+
+    /**
+     * Parse response body and return data in array.
+     *
+     * @param string $responseBody
+     * @return array
+     * @throws \OAuth\Common\Http\Exception\TokenResponseException
+     */
+    protected function _parseResponseBody($responseBody)
+    {
+        if (!is_string($responseBody)) {
+            throw new TokenResponseException("Response body is expected to be a string.");
+        }
+        parse_str($responseBody, $data);
+        if (null === $data || !is_array($data)) {
+            throw new TokenResponseException('Unable to parse response.');
+        } elseif (isset($data['error'])) {
+            throw new TokenResponseException("Error occurred: '{$data['error']}'");
+        }
+        return $data;
+    }
+
+    /**
+     * Retrieve oAuth verifier that was obtained during request token request.
+     *
+     * @return string
+     * @throws \OAuth\Common\Http\Exception\TokenResponseException
+     */
+    public function getOauthVerifier()
+    {
+        if (!isset($this->_oauthVerifier) || isEmpty($this->_oauthVerifier)) {
+            throw new TokenResponseException("oAuth verifier must be obtained during request token request.");
+        }
+        return $this->_oauthVerifier;
+    }
+
+    /**
+     * @override to fix since parent implementation from lib not sending the oauth_verifier when requesting access token
+     * Builds the authorization header for an authenticated API request
+     * @param string $method
+     * @param UriInterface $uri the uri the request is headed
+     * @param \OAuth\OAuth1\Token\TokenInterface $token
+     * @param $bodyParams array
+     * @return string
+     */
+    protected function buildAuthorizationHeaderForAPIRequest(
+        $method,
+        UriInterface $uri,
+        TokenInterface $token,
+        $bodyParams = null
+    ) {
+        $this->signature->setTokenSecret($token->getAccessTokenSecret());
+        $parameters = $this->getBasicAuthorizationHeaderInfo();
+        if (isset($parameters['oauth_callback'])) {
+            unset($parameters['oauth_callback']);
+        }
+
+        $parameters = array_merge($parameters, ['oauth_token' => $token->getAccessToken()]);
+        $parameters = array_merge($parameters, $bodyParams);
+        $parameters['oauth_signature'] = $this->signature->getSignature($uri, $parameters, $method);
+
+        $authorizationHeader = 'OAuth ';
+        $delimiter = '';
+
+        foreach ($parameters as $key => $value) {
+            $authorizationHeader .= $delimiter . rawurlencode($key) . '="' . rawurlencode($value) . '"';
+            $delimiter = ', ';
+        }
+
+        return $authorizationHeader;
+    }
+
+    /**
+     * Builds the oAuth authorization header for an authenticated API request
+     *
+     * @param UriInterface $uri the uri the request is headed
+     * @param \OAuth\OAuth1\Token\TokenInterface $token
+     * @param string $tokenSecret used to verify the passed token
+     * @param array $bodyParams
+     * @param string $method HTTP method to use
+     * @return array
+     */
+    public function buildOauthAuthorizationHeader($uri, $token, $tokenSecret, $bodyParams, $method = 'GET')
+    {
+        $uri = new Uri($uri);
+        $tokenObj = new StdOAuth1Token();
+        $tokenObj->setAccessToken($token);
+        $tokenObj->setAccessTokenSecret($tokenSecret);
+        $tokenObj->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES);
+        return [
+            'Authorization: ' . $this->buildAuthorizationHeaderForAPIRequest($method, $uri, $tokenObj, $bodyParams)
+        ];
+    }
+
+    /**
+     * Builds the bearer token authorization header
+     *
+     * @param string $token
+     * @return array
+     */
+    public function buildBearerTokenAuthorizationHeader($token)
+    {
+        return [
+            'Authorization: Bearer ' . $token
+        ];
+    }
+
+    /**
+     * Validates a Test REST api call access using oauth access token
+     *
+     * @param TokenInterface $token The access token.
+     * @param string $method HTTP method.
+     * @return array
+     * @throws TokenResponseException
+     */
+    public function validateAccessToken($token, $method = 'GET')
+    {
+        //Need to add Accept header else Magento errors out with 503
+        $extraAuthenticationHeaders = ['Accept' => 'application/json'];
+
+        $this->signature->setTokenSecret($token->getAccessTokenSecret());
+
+        $authorizationHeader = [
+            'Authorization' => $this->buildAuthorizationHeaderForAPIRequest(
+                $method,
+                $this->getTestApiEndpoint(),
+                $token,
+                []
+            ),
+        ];
+
+        $headers = array_merge($authorizationHeader, $extraAuthenticationHeaders);
+
+        $responseBody = $this->httpClient->retrieveResponse($this->getTestApiEndpoint(), [], $headers, $method);
+
+        return json_decode($responseBody);
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient/Signature.php b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient/Signature.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a2a6c73692bf1c529cd05d23295022085778a32
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/Rest/OauthClient/Signature.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestFramework\Authentication\Rest\OauthClient;
+
+use OAuth\Common\Http\Uri\UriInterface;
+
+/**
+ * Signature class for Magento REST API.
+ */
+class Signature extends \OAuth\OAuth1\Signature\Signature
+{
+    /**
+     * {@inheritdoc}
+     *
+     * In addition to the original method, allows array parameters for filters.
+     */
+    public function getSignature(UriInterface $uri, array $params, $method = 'POST')
+    {
+        $queryStringData = !$uri->getQuery() ? [] : array_reduce(
+            explode('&', $uri->getQuery()),
+            function ($carry, $item) {
+                list($key, $value) = explode('=', $item, 2);
+                $carry[rawurldecode($key)] = rawurldecode($value);
+                return $carry;
+            },
+            []
+        );
+
+        foreach (array_merge($queryStringData, $params) as $key => $value) {
+            $signatureData[rawurlencode($key)] = rawurlencode($value);
+        }
+
+        ksort($signatureData);
+
+        // determine base uri
+        $baseUri = $uri->getScheme() . '://' . $uri->getRawAuthority();
+
+        if ('/' == $uri->getPath()) {
+            $baseUri .= $uri->hasExplicitTrailingHostSlash() ? '/' : '';
+        } else {
+            $baseUri .= $uri->getPath();
+        }
+
+        $baseString = strtoupper($method) . '&';
+        $baseString .= rawurlencode($baseUri) . '&';
+        $baseString .= rawurlencode($this->buildSignatureDataString($signatureData));
+
+        return base64_encode($this->hash($baseString));
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Bootstrap/WebapiDocBlock.php b/dev/tests/api-functional/framework/Magento/TestFramework/Bootstrap/WebapiDocBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..a764f9988864f3053ae6890605d4f54452a78b24
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Bootstrap/WebapiDocBlock.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Bootstrap of the custom Web API DocBlock annotations.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\Bootstrap;
+
+class WebapiDocBlock extends \Magento\TestFramework\Bootstrap\DocBlock
+{
+    /**
+     * Get list of subscribers. In addition, register <b>magentoApiDataFixture</b> annotation processing.
+     *
+     * @param \Magento\TestFramework\Application $application
+     * @return array
+     */
+    protected function _getSubscribers(\Magento\TestFramework\Application $application)
+    {
+        $subscribers = parent::_getSubscribers($application);
+        array_unshift($subscribers, new \Magento\TestFramework\Annotation\ApiDataFixture($this->_fixturesBaseDir));
+        return $subscribers;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Helper/Customer.php b/dev/tests/api-functional/framework/Magento/TestFramework/Helper/Customer.php
new file mode 100644
index 0000000000000000000000000000000000000000..77033575557430fc8b296893bc099b1b41d3152c
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/Helper/Customer.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\Helper;
+
+use Magento\Customer\Api\Data\AddressDataBuilder;
+use Magento\Customer\Api\Data\CustomerDataBuilder;
+use Magento\Customer\Api\Data\CustomerInterface;
+use Magento\Customer\Model\Data\Customer as CustomerData;
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class Customer extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/customers';
+    const SERVICE_NAME = 'customerAccountManagementV1';
+    const SERVICE_VERSION = 'V1';
+
+    const CONFIRMATION = 'a4fg7h893e39d';
+    const CREATED_AT = '2013-11-05';
+    const CREATED_IN = 'default';
+    const STORE_NAME = 'Store Name';
+    const DOB = '1970-01-01';
+    const GENDER = 'Male';
+    const GROUP_ID = 1;
+    const MIDDLENAME = 'A';
+    const PREFIX = 'Mr.';
+    const STORE_ID = 1;
+    const SUFFIX = 'Esq.';
+    const TAXVAT = '12';
+    const WEBSITE_ID = 1;
+
+    /** Sample values for testing */
+    const FIRSTNAME = 'Jane';
+    const LASTNAME = 'Doe';
+    const PASSWORD = 'test@123';
+
+    const ADDRESS_CITY1 = 'CityM';
+    const ADDRESS_CITY2 = 'CityX';
+    const ADDRESS_REGION_CODE1 = 'AL';
+    const ADDRESS_REGION_CODE2 = 'AL';
+
+    /** @var AddressDataBuilder */
+    private $addressBuilder;
+
+    /** @var CustomerDataBuilder */
+    private $customerBuilder;
+
+    /** @var DataObjectProcessor */
+    private $dataObjectProcessor;
+
+    public function __construct($name = null, array $data = [], $dataName = '')
+    {
+        parent::__construct($name, $data, $dataName);
+
+        $this->addressBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\AddressDataBuilder'
+        );
+
+        $this->customerBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\CustomerDataBuilder'
+        );
+
+        $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Reflection\DataObjectProcessor'
+        );
+    }
+
+    public function createSampleCustomer()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'CreateAccount',
+            ],
+        ];
+        $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
+            $this->createSampleCustomerDataObject(),
+            '\Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $requestData = ['customer' => $customerDataArray, 'password' => self::PASSWORD];
+        $customerData = $this->_webApiCall($serviceInfo, $requestData);
+        return $customerData;
+    }
+
+    /**
+     * Create customer using setters.
+     *
+     * @return CustomerInterface
+     */
+    public function createSampleCustomerDataObject()
+    {
+        $this->addressBuilder
+            ->setCountryId('US')
+            ->setDefaultBilling(true)
+            ->setDefaultShipping(true)
+            ->setPostcode('75477')
+            ->setRegion(
+                Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\RegionDataBuilder')
+                    ->setRegionCode(self::ADDRESS_REGION_CODE1)
+                    ->setRegion('Alabama')
+                    ->setRegionId(1)
+                    ->create()
+            )
+            ->setStreet(['Green str, 67'])
+            ->setTelephone('3468676')
+            ->setCity(self::ADDRESS_CITY1)
+            ->setFirstname('John')
+            ->setLastname('Smith');
+        $address1 = $this->dataObjectProcessor->buildOutputDataArray(
+            $this->addressBuilder->create(),
+            'Magento\Customer\Api\Data\AddressInterface'
+        );
+
+        $this->addressBuilder
+            ->setCountryId('US')
+            ->setDefaultBilling(false)
+            ->setDefaultShipping(false)
+            ->setPostcode('47676')
+            ->setRegion(
+                Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\RegionDataBuilder')
+                    ->setRegionCode(self::ADDRESS_REGION_CODE2)
+                    ->setRegion('Alabama')
+                    ->setRegionId(1)
+                    ->create()
+            )
+            ->setStreet(['Black str, 48', 'Building D'])
+            ->setCity(self::ADDRESS_CITY2)
+            ->setTelephone('3234676')
+            ->setFirstname('John')
+            ->setLastname('Smith');
+        $address2 = $this->dataObjectProcessor->buildOutputDataArray(
+            $this->addressBuilder->create(),
+            'Magento\Customer\Api\Data\AddressInterface'
+        );
+
+        $customerData = [
+            CustomerData::FIRSTNAME => self::FIRSTNAME,
+            CustomerData::LASTNAME => self::LASTNAME,
+            CustomerData::EMAIL => 'janedoe' . uniqid() . '@example.com',
+            CustomerData::CONFIRMATION => self::CONFIRMATION,
+            CustomerData::CREATED_AT => self::CREATED_AT,
+            CustomerData::CREATED_IN => self::STORE_NAME,
+            CustomerData::DOB => self::DOB,
+            CustomerData::GENDER => self::GENDER,
+            CustomerData::GROUP_ID => self::GROUP_ID,
+            CustomerData::MIDDLENAME => self::MIDDLENAME,
+            CustomerData::PREFIX => self::PREFIX,
+            CustomerData::STORE_ID => self::STORE_ID,
+            CustomerData::SUFFIX => self::SUFFIX,
+            CustomerData::TAXVAT => self::TAXVAT,
+            CustomerData::WEBSITE_ID => self::WEBSITE_ID,
+            CustomerData::KEY_ADDRESSES => [$address1, $address2],
+            'custom_attributes' => [
+                [
+                    'attribute_code' => 'disable_auto_group_change',
+                    'value' => '0',
+                ],
+            ],
+        ];
+        return $this->customerBuilder->populateWithArray($customerData)->create();
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest.php
new file mode 100644
index 0000000000000000000000000000000000000000..91a12efba587b2d5a22bfccee576f1a875af0c3a
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Test client for REST API testing.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestFramework\TestCase\Webapi\Adapter;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Model\Rest\Config;
+
+class Rest implements \Magento\TestFramework\TestCase\Webapi\AdapterInterface
+{
+    /** @var \Magento\Webapi\Model\Config */
+    protected $_config;
+
+    /** @var \Magento\Integration\Model\Oauth\Consumer */
+    protected static $_consumer;
+
+    /** @var \Magento\Integration\Model\Oauth\Token */
+    protected static $_token;
+
+    /** @var string */
+    protected static $_consumerKey;
+
+    /** @var string */
+    protected static $_consumerSecret;
+
+    /** @var string */
+    protected static $_verifier;
+
+    /** @var \Magento\TestFramework\TestCase\Webapi\Adapter\Rest\CurlClient */
+    protected $curlClient;
+
+    /** @var \Magento\TestFramework\TestCase\Webapi\Adapter\Rest\DocumentationGenerator */
+    protected $documentationGenerator;
+
+    /** @var string */
+    protected $defaultStoreCode;
+
+    /**
+     * Initialize dependencies.
+     */
+    public function __construct()
+    {
+        /** @var $objectManager \Magento\TestFramework\ObjectManager */
+        $objectManager = Bootstrap::getObjectManager();
+        $this->_config = $objectManager->get('Magento\Webapi\Model\Config');
+        $this->curlClient = $objectManager->get('Magento\TestFramework\TestCase\Webapi\Adapter\Rest\CurlClient');
+        $this->documentationGenerator = $objectManager->get(
+            'Magento\TestFramework\TestCase\Webapi\Adapter\Rest\DocumentationGenerator'
+        );
+        $this->defaultStoreCode = Bootstrap::getObjectManager()
+            ->get('Magento\Store\Model\StoreManagerInterface')
+            ->getStore()
+            ->getCode();
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws \Exception
+     */
+    public function call($serviceInfo, $arguments = [])
+    {
+        $resourcePath = '/' . $this->defaultStoreCode . $this->_getRestResourcePath($serviceInfo);
+        $httpMethod = $this->_getRestHttpMethod($serviceInfo);
+        //Get a valid token
+        $accessCredentials = \Magento\TestFramework\Authentication\OauthHelper::getApiAccessCredentials();
+        /** @var $oAuthClient \Magento\TestFramework\Authentication\Rest\OauthClient */
+        $oAuthClient = $accessCredentials['oauth_client'];
+        $urlFormEncoded = false;
+        // we're always using JSON
+        $authHeader = [];
+        $restServiceInfo = $serviceInfo['rest'];
+        if (array_key_exists('token', $restServiceInfo)) {
+            $authHeader = $oAuthClient->buildBearerTokenAuthorizationHeader($restServiceInfo['token']);
+        } else {
+            $authHeader = $oAuthClient->buildOauthAuthorizationHeader(
+                $this->curlClient->constructResourceUrl($resourcePath),
+                $accessCredentials['key'],
+                $accessCredentials['secret'],
+                ($httpMethod == 'PUT' || $httpMethod == 'POST') && $urlFormEncoded ? $arguments : [],
+                $httpMethod
+            );
+        }
+        $authHeader = array_merge($authHeader, ['Accept: application/json', 'Content-Type: application/json']);
+        switch ($httpMethod) {
+            case Config::HTTP_METHOD_GET:
+                $response = $this->curlClient->get($resourcePath, [], $authHeader);
+                break;
+            case Config::HTTP_METHOD_POST:
+                $response = $this->curlClient->post($resourcePath, $arguments, $authHeader);
+                break;
+            case Config::HTTP_METHOD_PUT:
+                $response = $this->curlClient->put($resourcePath, $arguments, $authHeader);
+                break;
+            case Config::HTTP_METHOD_DELETE:
+                $response = $this->curlClient->delete($resourcePath, $authHeader);
+                break;
+            default:
+                throw new \LogicException("HTTP method '{$httpMethod}' is not supported.");
+        }
+        if (defined('GENERATE_REST_DOCUMENTATION') && GENERATE_REST_DOCUMENTATION) {
+            $this->documentationGenerator->generateDocumentation($httpMethod, $resourcePath, $arguments, $response);
+        }
+        return $response;
+    }
+
+    /**
+     * Retrieve REST endpoint from $serviceInfo array and return it to the caller.
+     *
+     * @param array $serviceInfo
+     * @return string
+     * @throws \Exception
+     */
+    protected function _getRestResourcePath($serviceInfo)
+    {
+        if (isset($serviceInfo['rest']['resourcePath'])) {
+            $resourcePath = $serviceInfo['rest']['resourcePath'];
+        }
+        if (!isset($resourcePath)) {
+            throw new \Exception("REST endpoint cannot be identified.");
+        }
+        return $resourcePath;
+    }
+
+    /**
+     * Retrieve HTTP method to be used in REST request.
+     *
+     * @param array $serviceInfo
+     * @return string
+     * @throws \Exception
+     */
+    protected function _getRestHttpMethod($serviceInfo)
+    {
+        if (isset($serviceInfo['rest']['httpMethod'])) {
+            $httpMethod = $serviceInfo['rest']['httpMethod'];
+        }
+        if (!isset($httpMethod)) {
+            throw new \Exception("REST HTTP method cannot be identified.");
+        }
+        return $httpMethod;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/CurlClient.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/CurlClient.php
new file mode 100644
index 0000000000000000000000000000000000000000..a907a4ca8b55e8f788f7be7da3d61eb1e6bba71b
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/CurlClient.php
@@ -0,0 +1,308 @@
+<?php
+/**
+ * Client for invoking REST API
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\TestCase\Webapi\Adapter\Rest;
+
+class CurlClient
+{
+    const EMPTY_REQUEST_BODY = 'Empty body';
+    /**
+     * @var string REST URL base path
+     */
+    protected $restBasePath = '/rest/';
+
+    /**
+     * @var array Response array
+     */
+    protected $responseArray;
+
+    /**
+     * @var array JSON Error code to error message mapping
+     */
+    protected $_jsonErrorMessages = [
+        JSON_ERROR_DEPTH => 'Maximum depth exceeded',
+        JSON_ERROR_STATE_MISMATCH => 'State mismatch',
+        JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
+        JSON_ERROR_SYNTAX => 'Syntax error, invalid JSON',
+    ];
+
+    /**
+     * Perform HTTP GET request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $data
+     * @param array $headers
+     * @return mixed
+     */
+    public function get($resourcePath, $data = [], $headers = [])
+    {
+        $url = $this->constructResourceUrl($resourcePath);
+        if (!empty($data)) {
+            $url .= '?' . http_build_query($data);
+        }
+
+        $curlOpts = [];
+        $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET;
+        $resp = $this->_invokeApi($url, $curlOpts, $headers);
+        $respArray = $this->_jsonDecode($resp["body"]);
+        return $respArray;
+    }
+
+    /**
+     * Perform HTTP POST request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $data
+     * @param array $headers
+     * @return mixed
+     */
+    public function post($resourcePath, $data, $headers = [])
+    {
+        return $this->_postOrPut($resourcePath, $data, false, $headers);
+    }
+
+    /**
+     * Perform HTTP PUT request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $data
+     * @param array $headers
+     * @return mixed
+     */
+    public function put($resourcePath, $data, $headers = [])
+    {
+        return $this->_postOrPut($resourcePath, $data, true, $headers);
+    }
+
+    /**
+     * Perform HTTP DELETE request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $headers
+     * @return mixed
+     */
+    public function delete($resourcePath, $headers = [])
+    {
+        $url = $this->constructResourceUrl($resourcePath);
+
+        $curlOpts = [];
+        $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE;
+
+        $resp = $this->_invokeApi($url, $curlOpts, $headers);
+        $respArray = $this->_jsonDecode($resp["body"]);
+
+        return $respArray;
+    }
+
+    /**
+     * Perform HTTP POST or PUT request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $data
+     * @param boolean $put Set true to post data as HTTP PUT operation (update). If this value is set to false,
+     *        HTTP POST (create) will be used
+     * @param array $headers
+     * @return mixed
+     */
+    protected function _postOrPut($resourcePath, $data, $put = false, $headers = [])
+    {
+        $url = $this->constructResourceUrl($resourcePath);
+
+        if (in_array("Content-Type: application/json", $headers)) {
+            // json encode data
+            if ($data != self::EMPTY_REQUEST_BODY) {
+                $data = $this->_jsonEncode($data);
+            } else {
+                $data = '';
+            }
+        }
+
+        $curlOpts = [];
+        if ($put) {
+            $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT;
+        } else {
+            $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST;
+        }
+        $headers[] = 'Content-Length: ' . strlen($data);
+        $curlOpts[CURLOPT_POSTFIELDS] = $data;
+
+        $this->responseArray = $this->_invokeApi($url, $curlOpts, $headers);
+        $respBodyArray = $this->_jsonDecode($this->responseArray["body"]);
+
+        return $respBodyArray;
+    }
+
+    /**
+     * Set Rest base path if available
+     *
+     * @param string $restBasePath
+     *
+     * @return void
+     */
+    public function setRestBasePath($restBasePath)
+    {
+        $this->restBasePath = $restBasePath;
+    }
+
+    /**
+     * Get current response array
+     *
+     * @return array
+     */
+    public function getCurrentResponseArray()
+    {
+        return $this->responseArray;
+    }
+
+    /**
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @return string resource URL
+     * @throws \Exception
+     */
+    public function constructResourceUrl($resourcePath)
+    {
+        return rtrim(TESTS_BASE_URL, '/') . $this->restBasePath . ltrim($resourcePath, '/');
+    }
+
+    /**
+     * Makes the REST api call using passed $curl object
+     *
+     * @param string $url
+     * @param array $additionalCurlOpts cURL Options
+     * @param array $headers
+     * @return array
+     * @throws \Exception
+     */
+    protected function _invokeApi($url, $additionalCurlOpts, $headers = [])
+    {
+        // initialize cURL
+        $curl = curl_init($url);
+        if ($curl === false) {
+            throw new \Exception("Error Initializing cURL for baseUrl: " . $url);
+        }
+
+        // get cURL options
+        $curlOpts = $this->_getCurlOptions($additionalCurlOpts, $headers);
+
+        // add CURL opts
+        foreach ($curlOpts as $opt => $val) {
+            curl_setopt($curl, $opt, $val);
+        }
+
+        $response = curl_exec($curl);
+        if ($response === false) {
+            throw new \Exception(curl_error($curl));
+        }
+
+        $resp = [];
+        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
+        $resp["header"] = substr($response, 0, $headerSize);
+        $resp["body"] = substr($response, $headerSize);
+
+        $resp["meta"] = curl_getinfo($curl);
+        if ($resp["meta"] === false) {
+            throw new \Exception(curl_error($curl));
+        }
+
+        curl_close($curl);
+
+        $meta = $resp["meta"];
+        if ($meta && $meta['http_code'] >= 400) {
+            throw new \Exception($resp["body"], $meta['http_code']);
+        }
+
+        return $resp;
+    }
+
+    /**
+     * Constructs and returns a curl options array
+     *
+     * @param array $customCurlOpts Additional / overridden cURL options
+     * @param array $headers
+     * @return array
+     */
+    protected function _getCurlOptions($customCurlOpts = [], $headers = [])
+    {
+        // default curl options
+        $curlOpts = [
+            CURLOPT_RETURNTRANSFER => true, // return result instead of echoing
+            CURLOPT_SSL_VERIFYPEER => false, // stop cURL from verifying the peer's certificate
+            CURLOPT_FOLLOWLOCATION => false, // follow redirects, Location: headers
+            CURLOPT_MAXREDIRS => 10, // but don't redirect more than 10 times
+            CURLOPT_HTTPHEADER => [],
+            CURLOPT_HEADER => 1,
+        ];
+
+        // merge headers
+        $headers = array_merge($curlOpts[CURLOPT_HTTPHEADER], $headers);
+        if (TESTS_XDEBUG_ENABLED) {
+            $headers[] = 'Cookie: XDEBUG_SESSION=' . TESTS_XDEBUG_SESSION;
+        }
+        $curlOpts[CURLOPT_HTTPHEADER] = $headers;
+
+        // merge custom Curl Options & return
+        foreach ($customCurlOpts as $opt => $val) {
+            $curlOpts[$opt] = $val;
+        }
+
+        return $curlOpts;
+    }
+
+    /**
+     * JSON encode with error checking
+     *
+     * @param mixed $data
+     * @return string
+     * @throws \Exception
+     */
+    protected function _jsonEncode($data)
+    {
+        $ret = json_encode($data);
+        $this->_checkJsonError($data);
+
+        // return the json String
+        return $ret;
+    }
+
+    /**
+     * Decode a JSON string with error checking
+     *
+     * @param string $data
+     * @param bool $asArray
+     * @throws \Exception
+     * @return mixed
+     */
+    protected function _jsonDecode($data, $asArray = true)
+    {
+        $ret = json_decode($data, $asArray);
+        $this->_checkJsonError($data);
+
+        // return the array
+        return $ret;
+    }
+
+    /**
+     * Checks for JSON error in the latest encoding / decoding and throws an exception in case of error
+     *
+     * @throws \Exception
+     */
+    protected function _checkJsonError()
+    {
+        $jsonError = json_last_error();
+        if ($jsonError !== JSON_ERROR_NONE) {
+            // find appropriate error message
+            $message = 'Unknown JSON Error';
+            if (isset($this->_jsonErrorMessages[$jsonError])) {
+                $message = $this->_jsonErrorMessages[$jsonError];
+            }
+
+            throw new \Exception(
+                'JSON Encoding / Decoding error: ' . $message . var_export(func_get_arg(0), true),
+                $jsonError
+            );
+        }
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/DocumentationGenerator.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/DocumentationGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..27cce9d7d6203ab6e45b1e4c7d19d1e49afaeeb5
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Rest/DocumentationGenerator.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestFramework\TestCase\Webapi\Adapter\Rest;
+
+/**
+ * Generator for documentation
+ *
+ */
+class DocumentationGenerator
+{
+    /**
+     * Generate documentation based on request-response data during REST requests.
+     *
+     * @param string $httpMethod
+     * @param string $resourcePath
+     * @param array $arguments
+     * @param array $response
+     */
+    public function generateDocumentation($httpMethod, $resourcePath, $arguments, $response)
+    {
+        $content = $this->generateHtmlContent($httpMethod, $resourcePath, $arguments, $response);
+        $filePath = $this->generateFileName($resourcePath);
+        if (is_null($filePath)) {
+            return;
+        }
+        if (!is_writable(dirname($filePath))) {
+            throw new \RuntimeException('Cannot write to documentation directory.');
+        } elseif (file_exists($filePath)) {
+            $fileContent = file_get_contents($filePath);
+            $endHtml = $this->generateHtmlFooter();
+            $fileContent = str_replace($endHtml, '', $fileContent);
+            $content = "{$fileContent}{$content}";
+            unlink($filePath);
+            file_put_contents($filePath, $content, FILE_APPEND);
+        } else {
+            file_put_contents($filePath, $content, FILE_APPEND);
+        }
+    }
+
+    /**
+     * Prepare HTML for the generated documentation.
+     *
+     * @param string $httpMethod
+     * @param string $resourcePath
+     * @param array $arguments
+     * @param array $response
+     * @return string
+     */
+    protected function generateHtmlContent($httpMethod, $resourcePath, $arguments, $response)
+    {
+        if (empty($arguments)) {
+            $arguments = 'This call does not accept a request body.';
+            $requestParametersHtml = '';
+        } else {
+            $requestParameters = $this->retrieveParametersAsHtml($arguments);
+            $arguments = json_encode($arguments, JSON_PRETTY_PRINT);
+            $requestParametersHtml = <<<HTML
+            <table class="docutils field-list" frame="void" rules="none"  width="400">
+                <colgroup>
+                    <col width="35%" class="field-name">
+                    <col  width="65%" class="field-body">
+                </colgroup>
+                <tbody valign="top">
+                <tr class="field-odd field">
+                    <th class="field-name">Request parameters:</th>
+                    <td class="field-body">
+                        <ul class="first last simple">
+                            {$requestParameters}
+                        </ul>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+HTML;
+        }
+        if (is_array($response)) {
+            $responseArrayKeys = array_keys($response);
+            $responseParameters = "Parameters should be specified manually.";
+            foreach ($responseArrayKeys as $key) {
+                if (!is_int($key)) {
+                    $responseParameters = '';
+                    break;
+                }
+            }
+        }
+        if (empty($responseParameters)) {
+            $responseParameters = $this->retrieveParametersAsHtml($response);
+        }
+        $response = json_encode($response, JSON_PRETTY_PRINT);
+        $responseParametersHtml = <<<HTML
+        <table class="docutils field-list" frame="void" rules="none"  width="400">
+            <colgroup>
+                <col width="35%" class="field-name">
+                <col  width="65%" class="field-body">
+            </colgroup>
+            <tbody valign="top">
+            <tr class="field-odd field">
+                <th class="field-name">Response attributes:</th>
+                <td class="field-body">
+                    <ul class="first last simple">
+                        {$responseParameters}
+                    </ul>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+HTML;
+        $resourcePath = urldecode($resourcePath);
+        $resource = str_replace('/', '-', preg_replace('#/\w*/V\d+/(.*)#', '${1}', $resourcePath));
+        $lowerCaseResource = strtolower($resource);
+        $lowerCaseMethod = strtolower($httpMethod);
+        $beginningHtml = <<<HTML
+<div class="col-xs-9" role="main">
+    <div class="bs-docs-section">
+HTML;
+        $headingHtml = <<<HTML
+        <h2 class="api2" id="$lowerCaseResource">$resource</h2>
+        <h3 class="api3" id="$lowerCaseMethod-$lowerCaseResource">$httpMethod $resourcePath</h3>
+        <h4 class="api4">Request</h4>
+HTML;
+        $responseHtml = <<<HTML
+        <h4 class="api4" id=”$lowerCaseResource-response>Response</h4>
+HTML;
+        $requestResponseParametersHtml = <<<HTML
+        <h3 class="api3" id="$lowerCaseResource-parameters">Request and response parameters</h3>
+HTML;
+        $endHtml = $this->generateHtmlFooter();
+        $content = "{$beginningHtml}{$headingHtml}<pre>{$arguments}</pre>{$responseHtml}<pre>{$response}"
+            . "</pre>{$requestResponseParametersHtml}{$requestParametersHtml}{$responseParametersHtml}{$endHtml}";
+        return $content;
+    }
+
+    /**
+     * Generate the end html text;
+     *
+     * @return string
+     */
+    protected function generateHtmlFooter()
+    {
+        $endHtml = <<<HTML
+        <h3 class="api3" id="products-responses">Response codes</h3>
+        <table class="docutils field-list" frame="void" rules="none" width="400">
+            <colgroup>
+                <col  width="35%" class="field-name">
+                <col  width="65%" class="field-body">
+            </colgroup>
+            <tbody valign="top">
+            <tr class="field-odd field">
+                <th class="field-name">Normal response codes:</th>
+                <td class="field-body">
+                    <ul class="first last simple">
+                        <li><strong>SUCCESS_CODE</strong> - SUCCESS_DESCRIPTION</li>
+                    </ul>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+        <table class="docutils field-list" frame="void" rules="none" width="400">
+            <colgroup>
+                <col  width="35%" class="field-name">
+                <col  width="65%" class="field-body">
+            </colgroup>
+            <tbody valign="top">
+            <tr class="field-odd field">
+                <th class="field-name">Error response codes:</th>
+                <td class="field-body">
+                    <ul class="first last simple">
+                        <li><strong>ERROR_CODE</strong> - ERROR_DESCRIPTION</li>
+                    </ul>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+HTML;
+        return $endHtml;
+    }
+
+    /**
+     * Generate a name of file
+     *
+     * @return string|null
+     * @throws \RuntimeException
+     */
+    protected function generateFileName()
+    {
+        $varDir = realpath(__DIR__ . '/../../../../../../..') . '/var';
+        $documentationDir = $varDir . '/log/rest-documentation/';
+        $debugBackTrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+        $pathToFile = $documentationDir;
+        $fileName = null;
+        foreach ($debugBackTrace as $traceItem) {
+            /** Test invocation trace item is the only item which has 3 elements, other trace items have 5 elements */
+            if (count($traceItem) == 3) {
+                /** Remove 'test' prefix from method name, e.g. testCreate => create */
+                $fileName = lcfirst(substr($traceItem['function'], 4));
+                /** Remove 'Test' suffix from test class name */
+                $pathToFile .= str_replace('\\', '/', substr($traceItem['class'], 0, -4)) . '/';
+                break;
+            }
+        }
+        if (!file_exists($pathToFile)) {
+            if (!mkdir($pathToFile, 0755, true)) {
+                throw new \RuntimeException('Unable to create missing directory for REST documentation generation');
+            }
+        }
+        if (!is_null($fileName)) {
+            $filePath = $pathToFile . $fileName . '.html';
+            return $filePath;
+        }
+        return null;
+    }
+
+    /**
+     * Retrieve parameters of response/request
+     *
+     * @param array|string $parameters
+     * @return string
+     */
+    protected function retrieveParametersAsHtml($parameters)
+    {
+        $parametersAsHtml = '';
+        if (is_array($parameters)) {
+            foreach (array_keys($parameters) as $parameter) {
+                $parametersAsHtml = $parametersAsHtml . '<li><strong>' . $parameter .
+                    '</strong> (<em>Change type manually!</em>) TBD.</li>';
+            }
+        } else {
+            $parametersAsHtml = '<li><strong>' . 'scalar_value' .
+                '</strong> (<em>Change type manually!</em>) TBD.</li>';
+        }
+        return $parametersAsHtml;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
new file mode 100644
index 0000000000000000000000000000000000000000..73f6d8a6582c314bf4e7447452e89e8f77d97be9
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Adapter/Soap.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\TestCase\Webapi\Adapter;
+
+use Magento\Framework\Api\SimpleDataObjectConverter;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Controller\Soap\Request\Handler as SoapHandler;
+
+/**
+ * Test client for SOAP API testing.
+ */
+class Soap implements \Magento\TestFramework\TestCase\Webapi\AdapterInterface
+{
+    const WSDL_BASE_PATH = '/soap';
+
+    /**
+     * SOAP client initialized with different WSDLs.
+     *
+     * @var \Zend\Soap\Client[]
+     */
+    protected $_soapClients = [];
+
+    /**
+     * @var \Magento\Webapi\Model\Soap\Config
+     */
+    protected $_soapConfig;
+
+    /**
+     * @var \Magento\Webapi\Helper\Data
+     */
+    protected $_helper;
+
+    /**
+     * @var SimpleDataObjectConverter
+     */
+    protected $_converter;
+
+    /**
+     * Initialize dependencies.
+     */
+    public function __construct()
+    {
+        /** @var $objectManager \Magento\TestFramework\ObjectManager */
+        $objectManager = Bootstrap::getObjectManager();
+        $this->_soapConfig = $objectManager->get('Magento\Webapi\Model\Soap\Config');
+        $this->_helper = $objectManager->get('Magento\Webapi\Helper\Data');
+        $this->_converter = $objectManager->get('Magento\Framework\Api\SimpleDataObjectConverter');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function call($serviceInfo, $arguments = [])
+    {
+        $soapOperation = $this->_getSoapOperation($serviceInfo);
+        $arguments = $this->_converter->convertKeysToCamelCase($arguments);
+        $soapResponse = $this->_getSoapClient($serviceInfo)->$soapOperation($arguments);
+        //Convert to snake case for tests to use same assertion data for both SOAP and REST tests
+        $result = (is_array($soapResponse) || is_object($soapResponse))
+            ? $this->toSnakeCase($this->_converter->convertStdObjectToArray($soapResponse, true))
+            : $soapResponse;
+        /** Remove result wrappers */
+        $result = isset($result[SoapHandler::RESULT_NODE_NAME]) ? $result[SoapHandler::RESULT_NODE_NAME] : $result;
+        return $result;
+    }
+
+    /**
+     * Get proper SOAP client instance that is initialized with with WSDL corresponding to requested service interface.
+     *
+     * @param string $serviceInfo PHP service interface name, should include version if present
+     * @return \Zend\Soap\Client
+     */
+    protected function _getSoapClient($serviceInfo)
+    {
+        $wsdlUrl = $this->generateWsdlUrl(
+            [$this->_getSoapServiceName($serviceInfo) . $this->_getSoapServiceVersion($serviceInfo)]
+        );
+        /** Check if there is SOAP client initialized with requested WSDL available */
+        if (!isset($this->_soapClients[$wsdlUrl])) {
+            $token = isset($serviceInfo['soap']['token']) ? $serviceInfo['soap']['token'] : null;
+            $this->_soapClients[$wsdlUrl] = $this->instantiateSoapClient($wsdlUrl, $token);
+        }
+        return $this->_soapClients[$wsdlUrl];
+    }
+
+    /**
+     * Create SOAP client instance and initialize it with provided WSDL URL.
+     *
+     * @param string $wsdlUrl
+     * @param string $token Authentication token
+     * @return \Zend\Soap\Client
+     */
+    public function instantiateSoapClient($wsdlUrl, $token = null)
+    {
+        $accessCredentials = $token
+            ? $token
+            : \Magento\TestFramework\Authentication\OauthHelper::getApiAccessCredentials()['key'];
+        $opts = ['http' => ['header' => "Authorization: Bearer " . $accessCredentials]];
+        $context = stream_context_create($opts);
+        $soapClient = new \Zend\Soap\Client($wsdlUrl);
+        $soapClient->setSoapVersion(SOAP_1_2);
+        $soapClient->setStreamContext($context);
+        if (TESTS_XDEBUG_ENABLED) {
+            $soapClient->setCookie('XDEBUG_SESSION', 1);
+        }
+        return $soapClient;
+    }
+
+    /**
+     * Generate WSDL URL.
+     *
+     * @param array $services e.g.<pre>
+     * array(
+     *     'catalogProductV1',
+     *     'customerV2'
+     * );</pre>
+     * @return string
+     */
+    public function generateWsdlUrl($services)
+    {
+        /** Sort list of services to avoid having different WSDL URLs for the identical lists of services. */
+        //TODO: This may change since same resource of multiple versions may be allowed after namespace changes
+        ksort($services);
+        /** @var \Magento\Store\Model\StoreManagerInterface $storeManager */
+        $storeManager = Bootstrap::getObjectManager()->get('Magento\Store\Model\StoreManagerInterface');
+        $storeCode = $storeManager->getStore()->getCode();
+        /** TESTS_BASE_URL is initialized in PHPUnit configuration */
+        $wsdlUrl = rtrim(TESTS_BASE_URL, '/') . self::WSDL_BASE_PATH . '/' . $storeCode . '?wsdl=1&services=';
+        $wsdlResourceArray = [];
+        foreach ($services as $serviceName) {
+            $wsdlResourceArray[] = $serviceName;
+        }
+        return $wsdlUrl . implode(",", $wsdlResourceArray);
+    }
+
+    /**
+     * Retrieve SOAP operation name from available service info.
+     *
+     * @param array $serviceInfo
+     * @return string
+     * @throws \LogicException
+     */
+    protected function _getSoapOperation($serviceInfo)
+    {
+        if (isset($serviceInfo['soap']['operation'])) {
+            $soapOperation = $serviceInfo['soap']['operation'];
+        } elseif (isset($serviceInfo['serviceInterface']) && isset($serviceInfo['method'])) {
+            $soapOperation = $this->_soapConfig->getSoapOperation(
+                $serviceInfo['serviceInterface'],
+                $serviceInfo['method']
+            );
+        } else {
+            throw new \LogicException("SOAP operation cannot be identified.");
+        }
+        return $soapOperation;
+    }
+
+    /**
+     * Retrieve service version from available service info.
+     *
+     * @param array $serviceInfo
+     * @return string
+     * @throws \LogicException
+     */
+    protected function _getSoapServiceVersion($serviceInfo)
+    {
+        if (isset($serviceInfo['soap']['operation'])) {
+            /*
+                TODO: Need to rework this to remove version call for serviceInfo array with 'operation' key
+                since version will be part of the service name
+            */
+            return '';
+        } elseif (isset($serviceInfo['serviceInterface'])) {
+            preg_match(
+                \Magento\Webapi\Model\Config::SERVICE_CLASS_PATTERN,
+                $serviceInfo['serviceInterface'],
+                $matches
+            );
+            if (isset($matches[3])) {
+                $version = $matches[3];
+            } else {
+                //TODO: Need to add this temporary version until version is added back for new MSC based services
+                $version = 1;
+                //throw new \LogicException("Service interface name is invalid.");
+            }
+        } else {
+            throw new \LogicException("Service version cannot be identified.");
+        }
+        /** Normalize version */
+        $version = 'V' . ltrim($version, 'vV');
+        return $version;
+    }
+
+    /**
+     * Retrieve service name from available service info.
+     *
+     * @param array $serviceInfo
+     * @return string
+     * @throws \LogicException
+     */
+    protected function _getSoapServiceName($serviceInfo)
+    {
+        if (isset($serviceInfo['soap']['service'])) {
+            $serviceName = $serviceInfo['soap']['service'];
+        } elseif (isset($serviceInfo['serviceInterface'])) {
+            $serviceName = $this->_helper->getServiceName($serviceInfo['serviceInterface'], false);
+        } else {
+            throw new \LogicException("Service name cannot be identified.");
+        }
+        return $serviceName;
+    }
+
+    /**
+     * Recursively transform array keys from camelCase to snake_case.
+     *
+     * Utility method for converting SOAP responses. Webapi framework's SOAP processing outputs
+     * snake case Data Object properties(ex. item_id) as camel case(itemId) to adhere to the WSDL.
+     * This method allows tests to use the same data for asserting both SOAP and REST responses.
+     *
+     * @param array $objectData An array of data.
+     * @return array The array with all camelCase keys converted to snake_case.
+     */
+    protected function toSnakeCase(array $objectData)
+    {
+        $data = [];
+        foreach ($objectData as $key => $value) {
+            $key = strtolower(preg_replace("/(?<=\\w)(?=[A-Z])/", "_$1", $key));
+            if (is_array($value)) {
+                $data[$key] = $this->toSnakeCase($value);
+            } else {
+                $data[$key] = $value;
+            }
+        }
+        return $data;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/AdapterInterface.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/AdapterInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e34d3cb702d6ae71e46ac6778660ec42a3f75d8f
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/AdapterInterface.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * API tests adapter interface.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\TestCase\Webapi;
+
+interface AdapterInterface
+{
+    /**
+     * Perform call to the specified service method.
+     *
+     * @param array $serviceInfo <pre>
+     * array(
+     *     'rest' => array(
+     *         'resourcePath' => $resourcePath, // e.g. /products/:id
+     *         'httpMethod' => $httpMethod,     // e.g. GET
+     *         'token' => '21hasbtlaqy8t3mj73kjh71cxxkqj4aq'    // optional : for token based Authentication. Will
+     *                                                             override default Oauth based authentication provided
+     *                                                             by test framework
+     *     ),
+     *     'soap' => array(
+     *         'service' => $soapService,    // soap service name with Version suffix e.g. catalogProductV1, customerV2
+     *         'operation' => $operation     // soap operation name e.g. catalogProductCreate
+     *     ),
+     *     OR
+     *     'serviceInterface' => $phpServiceInterfaceName, // e.g. \Magento\Catalog\Api\ProductInterface
+     *     'method' => $serviceMethodName                  // e.g. create
+     *     'entityId' => $entityId                         // is used in REST route placeholder (if applicable)
+     * );
+     * </pre>
+     * @param array $arguments
+     * @return array|string|int|float|bool
+     */
+    public function call($serviceInfo, $arguments = []);
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Curl.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Curl.php
new file mode 100644
index 0000000000000000000000000000000000000000..655f31579c729e40b5922e5f39f87ae66c4beff7
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/Webapi/Curl.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\TestFramework\TestCase\Webapi;
+
+/**
+ * A Curl client that can be called independently, outside of REST controller.
+ *
+ * Used by CookieManager tests.
+ */
+class Curl extends Adapter\Rest\CurlClient
+{
+    const COOKIE_HEADER = 'Set-Cookie: ';
+
+    /**
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @return string resource URL
+     * @throws \Exception
+     */
+    public function constructResourceUrl($resourcePath)
+    {
+        return rtrim(TESTS_BASE_URL, '/') . ltrim($resourcePath, '/');
+    }
+
+    /**
+     * Perform HTTP GET request
+     *
+     * @param string $resourcePath Resource URL like /V1/Resource1/123
+     * @param array $data
+     * @param array $headers
+     * @return array
+     */
+    public function get($resourcePath, $data = [], $headers = [])
+    {
+        $url = $this->constructResourceUrl($resourcePath);
+        if (!empty($data)) {
+            $url .= '?' . http_build_query($data);
+        }
+
+        $curlOpts = [];
+        $curlOpts[CURLOPT_CUSTOMREQUEST] = \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET;
+        $curlOpts[CURLOPT_SSLVERSION] = 3;
+        $response = $this->_invokeApi($url, $curlOpts, $headers);
+        $response['cookies'] = $this->cookieParse($response['header']);
+        return $response;
+    }
+
+    /**
+     * Takes a string in the form of an HTTP header block, returns cookie data.
+     *
+     * Return array is in the form of:
+     *  [
+     *      [
+     *          'name' = <cookie_name>,
+     *          'value' = <cookie_value>,
+     *          <cookie_metadata_name> => <cookie_metadata_value> || 'true'
+     *      ],
+     *  ]
+     *
+     * @param $headerBlock
+     * @return array
+     */
+    private function cookieParse($headerBlock)
+    {
+        $header = explode("\r\n", $headerBlock);
+        $cookies = [];
+        foreach ($header as $line) {
+            $line = trim($line);
+            if (substr($line, 0, strlen(self::COOKIE_HEADER)) == self::COOKIE_HEADER) {
+                $line = trim(substr($line, strlen(self::COOKIE_HEADER)));
+                $cookieData = [];
+                // Check if cookie contains attributes
+                if (strpos($line, ';') === false) {
+                    // no attributes, just name and value
+                    list($cookieData['name'], $cookieData['value']) = explode('=', $line);
+                } else {
+                    // has attributes, must parse them out and loop through
+                    list($nvPair, $cookieMetadata) = explode(';', $line, 2);
+                    list($cookieData['name'], $cookieData['value']) = explode('=', $nvPair);
+                    $rawCookieData = explode(';', $cookieMetadata);
+                    foreach ($rawCookieData as $keyValuePairs) {
+                        list($key, $value) = array_merge(explode('=', $keyValuePairs), ['true']);
+                        $cookieData[strtolower(trim($key))] = trim($value);
+                    }
+                }
+                $cookies[] = $cookieData;
+            }
+        }
+        return $cookies;
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/WebapiAbstract.php b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/WebapiAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..d02247b75a0838f352d1f3844dff87ab36cf475e
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/TestCase/WebapiAbstract.php
@@ -0,0 +1,665 @@
+<?php
+/**
+ * Generic test case for Web API functional tests.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework\TestCase;
+
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Filesystem;
+use Magento\Webapi\Model\Soap\Fault;
+
+abstract class WebapiAbstract extends \PHPUnit_Framework_TestCase
+{
+    /** TODO: Reconsider implementation of fixture-management methods after implementing several tests */
+    /**#@+
+     * Auto tear down options in setFixture
+     */
+    const AUTO_TEAR_DOWN_DISABLED = 0;
+    const AUTO_TEAR_DOWN_AFTER_METHOD = 1;
+    const AUTO_TEAR_DOWN_AFTER_CLASS = 2;
+    /**#@-*/
+
+    /**#@+
+     * Web API adapters that are used to perform actual calls.
+     */
+    const ADAPTER_SOAP = 'soap';
+    const ADAPTER_REST = 'rest';
+    /**#@-*/
+
+    /**
+     * Application cache model.
+     *
+     * @var \Magento\Framework\App\Cache
+     */
+    protected $_appCache;
+
+    /**
+     * The list of models to be deleted automatically in tearDown().
+     *
+     * @var array
+     */
+    protected $_modelsToDelete = [];
+
+    /**
+     * Namespace for fixtures is different for each test case.
+     *
+     * @var string
+     */
+    protected static $_fixturesNamespace;
+
+    /**
+     * The list of registered fixtures.
+     *
+     * @var array
+     */
+    protected static $_fixtures = [];
+
+    /**
+     * Fixtures to be deleted in tearDown().
+     *
+     * @var array
+     */
+    protected static $_methodLevelFixtures = [];
+
+    /**
+     * Fixtures to be deleted in tearDownAfterClass().
+     *
+     * @var array
+     */
+    protected static $_classLevelFixtures = [];
+
+    /**
+     * Original Magento config values.
+     *
+     * @var array
+     */
+    protected $_origConfigValues = [];
+
+    /**
+     * The list of instantiated Web API adapters.
+     *
+     * @var \Magento\TestFramework\TestCase\Webapi\AdapterInterface[]
+     */
+    protected $_webApiAdapters;
+
+    /**
+     * The list of available Web API adapters.
+     *
+     * @var array
+     */
+    protected $_webApiAdaptersMap = [
+        self::ADAPTER_SOAP => 'Magento\TestFramework\TestCase\Webapi\Adapter\Soap',
+        self::ADAPTER_REST => 'Magento\TestFramework\TestCase\Webapi\Adapter\Rest',
+    ];
+
+    /**
+     * Initialize fixture namespaces.
+     */
+    public static function setUpBeforeClass()
+    {
+        parent::setUpBeforeClass();
+        self::_setFixtureNamespace();
+    }
+
+    /**
+     * Run garbage collector for cleaning memory
+     *
+     * @return void
+     */
+    public static function tearDownAfterClass()
+    {
+        //clear garbage in memory
+        if (version_compare(PHP_VERSION, '5.3', '>=')) {
+            gc_collect_cycles();
+        }
+
+        $fixtureNamespace = self::_getFixtureNamespace();
+        if (isset(self::$_classLevelFixtures[$fixtureNamespace])
+            && count(self::$_classLevelFixtures[$fixtureNamespace])
+        ) {
+            self::_deleteFixtures(self::$_classLevelFixtures[$fixtureNamespace]);
+        }
+
+        //ever disable secure area on class down
+        self::_enableSecureArea(false);
+        self::_unsetFixtureNamespace();
+        parent::tearDownAfterClass();
+    }
+
+    /**
+     * Call safe delete for models which added to delete list
+     * Restore config values changed during the test
+     *
+     * @return void
+     */
+    protected function tearDown()
+    {
+        $fixtureNamespace = self::_getFixtureNamespace();
+        if (isset(self::$_methodLevelFixtures[$fixtureNamespace])
+            && count(self::$_methodLevelFixtures[$fixtureNamespace])
+        ) {
+            self::_deleteFixtures(self::$_methodLevelFixtures[$fixtureNamespace]);
+        }
+        $this->_callModelsDelete();
+        $this->_restoreAppConfig();
+        parent::tearDown();
+    }
+
+    /**
+     * Perform Web API call to the system under test.
+     *
+     * @see \Magento\TestFramework\TestCase\Webapi\AdapterInterface::call()
+     * @param array $serviceInfo
+     * @param array $arguments
+     * @param string|null $webApiAdapterCode
+     * @return array|int|string|float|bool Web API call results
+     */
+    protected function _webApiCall($serviceInfo, $arguments = [], $webApiAdapterCode = null)
+    {
+        if (is_null($webApiAdapterCode)) {
+            /** Default adapter code is defined in PHPUnit configuration */
+            $webApiAdapterCode = strtolower(TESTS_WEB_API_ADAPTER);
+        }
+        return $this->_getWebApiAdapter($webApiAdapterCode)->call($serviceInfo, $arguments);
+    }
+
+    /**
+     * Mark test to be executed for SOAP adapter only.
+     */
+    protected function _markTestAsSoapOnly($message = null)
+    {
+        if (TESTS_WEB_API_ADAPTER != self::ADAPTER_SOAP) {
+            $this->markTestSkipped($message ? $message : "The test is intended to be executed for SOAP adapter only.");
+        }
+    }
+
+    /**
+     * Mark test to be executed for REST adapter only.
+     */
+    protected function _markTestAsRestOnly($message = null)
+    {
+        if (TESTS_WEB_API_ADAPTER != self::ADAPTER_REST) {
+            $this->markTestSkipped($message ? $message : "The test is intended to be executed for REST adapter only.");
+        }
+    }
+
+    /**
+     * Set fixture to registry
+     *
+     * @param string $key
+     * @param mixed $fixture
+     * @param int $tearDown
+     * @return void
+     */
+    public static function setFixture($key, $fixture, $tearDown = self::AUTO_TEAR_DOWN_AFTER_METHOD)
+    {
+        $fixturesNamespace = self::_getFixtureNamespace();
+        if (!isset(self::$_fixtures[$fixturesNamespace])) {
+            self::$_fixtures[$fixturesNamespace] = [];
+        }
+        self::$_fixtures[$fixturesNamespace][$key] = $fixture;
+        if ($tearDown == self::AUTO_TEAR_DOWN_AFTER_METHOD) {
+            if (!isset(self::$_methodLevelFixtures[$fixturesNamespace])) {
+                self::$_methodLevelFixtures[$fixturesNamespace] = [];
+            }
+            self::$_methodLevelFixtures[$fixturesNamespace][] = $key;
+        } else {
+            if ($tearDown == self::AUTO_TEAR_DOWN_AFTER_CLASS) {
+                if (!isset(self::$_classLevelFixtures[$fixturesNamespace])) {
+                    self::$_classLevelFixtures[$fixturesNamespace] = [];
+                }
+                self::$_classLevelFixtures[$fixturesNamespace][] = $key;
+            }
+        }
+    }
+
+    /**
+     * Get fixture by key
+     *
+     * @param string $key
+     * @return mixed
+     */
+    public static function getFixture($key)
+    {
+        $fixturesNamespace = self::_getFixtureNamespace();
+        if (array_key_exists($key, self::$_fixtures[$fixturesNamespace])) {
+            return self::$_fixtures[$fixturesNamespace][$key];
+        }
+        return null;
+    }
+
+    /**
+     * Call safe delete for model
+     *
+     * @param \Magento\Framework\Model\AbstractModel $model
+     * @param bool $secure
+     * @return \Magento\TestFramework\TestCase\WebapiAbstract
+     */
+    public static function callModelDelete($model, $secure = false)
+    {
+        if ($model instanceof \Magento\Framework\Model\AbstractModel && $model->getId()) {
+            if ($secure) {
+                self::_enableSecureArea();
+            }
+            $model->delete();
+            if ($secure) {
+                self::_enableSecureArea(false);
+            }
+        }
+    }
+
+    /**
+     * Call safe delete for model
+     *
+     * @param \Magento\Framework\Model\AbstractModel $model
+     * @param bool $secure
+     * @return \Magento\TestFramework\TestCase\WebapiAbstract
+     */
+    public function addModelToDelete($model, $secure = false)
+    {
+        $this->_modelsToDelete[] = ['model' => $model, 'secure' => $secure];
+        return $this;
+    }
+
+    /**
+     * Get Web API adapter (create if requested one does not exist).
+     *
+     * @param string $webApiAdapterCode
+     * @return \Magento\TestFramework\TestCase\Webapi\AdapterInterface
+     * @throws \LogicException When requested Web API adapter is not declared
+     */
+    protected function _getWebApiAdapter($webApiAdapterCode)
+    {
+        if (!isset($this->_webApiAdapters[$webApiAdapterCode])) {
+            if (!isset($this->_webApiAdaptersMap[$webApiAdapterCode])) {
+                throw new \LogicException(
+                    sprintf('Declaration of the requested Web API adapter "%s" was not found.', $webApiAdapterCode)
+                );
+            }
+            $this->_webApiAdapters[$webApiAdapterCode] = new $this->_webApiAdaptersMap[$webApiAdapterCode]();
+        }
+        return $this->_webApiAdapters[$webApiAdapterCode];
+    }
+
+    /**
+     * Set fixtures namespace
+     *
+     * @throws \RuntimeException
+     */
+    protected static function _setFixtureNamespace()
+    {
+        if (!is_null(self::$_fixturesNamespace)) {
+            throw new \RuntimeException('Fixture namespace is already set.');
+        }
+        self::$_fixturesNamespace = uniqid();
+    }
+
+    /**
+     * Unset fixtures namespace
+     */
+    protected static function _unsetFixtureNamespace()
+    {
+        $fixturesNamespace = self::_getFixtureNamespace();
+        unset(self::$_fixtures[$fixturesNamespace]);
+        self::$_fixturesNamespace = null;
+    }
+
+    /**
+     * Get fixtures namespace
+     *
+     * @throws \RuntimeException
+     * @return string
+     */
+    protected static function _getFixtureNamespace()
+    {
+        $fixtureNamespace = self::$_fixturesNamespace;
+        if (is_null($fixtureNamespace)) {
+            throw new \RuntimeException('Fixture namespace must be set.');
+        }
+        return $fixtureNamespace;
+    }
+
+    /**
+     * Enable secure/admin area
+     *
+     * @param bool $flag
+     * @return void
+     */
+    protected static function _enableSecureArea($flag = true)
+    {
+        /** @var $objectManager \Magento\TestFramework\ObjectManager */
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        $objectManager->get('Magento\Framework\Registry')->unregister('isSecureArea');
+        if ($flag) {
+            $objectManager->get('Magento\Framework\Registry')->register('isSecureArea', $flag);
+        }
+    }
+
+    /**
+     * Call delete models from list
+     *
+     * @return \Magento\TestFramework\TestCase\WebapiAbstract
+     */
+    protected function _callModelsDelete()
+    {
+        if ($this->_modelsToDelete) {
+            foreach ($this->_modelsToDelete as $key => $modelData) {
+                /** @var $model \Magento\Framework\Model\AbstractModel */
+                $model = $modelData['model'];
+                $this->callModelDelete($model, $modelData['secure']);
+                unset($this->_modelsToDelete[$key]);
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Check if all error messages are expected ones
+     *
+     * @param array $expectedMessages
+     * @param array $receivedMessages
+     */
+    protected function _assertMessagesEqual($expectedMessages, $receivedMessages)
+    {
+        foreach ($receivedMessages as $message) {
+            $this->assertContains($message, $expectedMessages, "Unexpected message: '{$message}'");
+        }
+        $expectedErrorsCount = count($expectedMessages);
+        $this->assertCount($expectedErrorsCount, $receivedMessages, 'Invalid messages quantity received');
+    }
+
+    /**
+     * Delete array of fixtures
+     *
+     * @param array $fixtures
+     */
+    protected static function _deleteFixtures($fixtures)
+    {
+        foreach ($fixtures as $fixture) {
+            self::deleteFixture($fixture, true);
+        }
+    }
+
+    /**
+     * Delete fixture by key
+     *
+     * @param string $key
+     * @param bool $secure
+     * @return void
+     */
+    public static function deleteFixture($key, $secure = false)
+    {
+        $fixturesNamespace = self::_getFixtureNamespace();
+        if (array_key_exists($key, self::$_fixtures[$fixturesNamespace])) {
+            self::callModelDelete(self::$_fixtures[$fixturesNamespace][$key], $secure);
+            unset(self::$_fixtures[$fixturesNamespace][$key]);
+        }
+    }
+
+    /** TODO: Remove methods below if not used, otherwise fix them (after having some tests implemented)*/
+
+    /**
+     * Get application cache model
+     *
+     * @return \Magento\Framework\App\Cache
+     */
+    protected function _getAppCache()
+    {
+        if (null === $this->_appCache) {
+            //set application path
+            $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+            /** @var \Magento\Framework\App\Config\ScopeConfigInterface $config */
+            $config = $objectManager->get('Magento\Framework\App\Config\ScopeConfigInterface');
+            $options = $config->getOptions();
+            $currentCacheDir = $options->getCacheDir();
+            $currentEtcDir = $options->getEtcDir();
+            /** @var Filesystem $filesystem */
+            $filesystem = $objectManager->get('Magento\Framework\Filesystem');
+            $options->setCacheDir($filesystem->getDirectoryRead(DirectoryList::CACHE)->getAbsolutePath());
+            $options->setEtcDir($filesystem->getDirectoryRead(DirectoryList::CONFIG)->getAbsolutePath());
+
+            $this->_appCache = $objectManager->get('Magento\Framework\App\Cache');
+
+            //revert paths options
+            $options->setCacheDir($currentCacheDir);
+            $options->setEtcDir($currentEtcDir);
+        }
+        return $this->_appCache;
+    }
+
+    /**
+     * Clean config cache of application
+     *
+     * @return bool
+     */
+    protected function _cleanAppConfigCache()
+    {
+        return $this->_getAppCache()->clean(\Magento\Framework\App\Config::CACHE_TAG);
+    }
+
+    /**
+     * Update application config data
+     *
+     * @param string $path              Config path with the form "section/group/node"
+     * @param string|int|null $value    Value of config item
+     * @param bool $cleanAppCache       If TRUE application cache will be refreshed
+     * @param bool $updateLocalConfig   If TRUE local config object will be updated too
+     * @param bool $restore             If TRUE config value will be restored after test run
+     * @return \Magento\TestFramework\TestCase\WebapiAbstract
+     * @throws \RuntimeException
+     */
+    protected function _updateAppConfig(
+        $path,
+        $value,
+        $cleanAppCache = true,
+        $updateLocalConfig = false,
+        $restore = false
+    ) {
+        list($section, $group, $node) = explode('/', $path);
+
+        if (!$section || !$group || !$node) {
+            throw new \RuntimeException(
+                sprintf('Config path must have view as "section/group/node" but now it "%s"', $path)
+            );
+        }
+
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var $config \Magento\Backend\Model\Config */
+        $config = $objectManager->create('Magento\Backend\Model\Config');
+        $data[$group]['fields'][$node]['value'] = $value;
+        $config->setSection($section)->setGroups($data)->save();
+
+        if ($restore && !isset($this->_origConfigValues[$path])) {
+            $this->_origConfigValues[$path] = (string)$objectManager->get(
+                'Magento\Framework\App\Config\ScopeConfigInterface'
+            )->getNode(
+                $path,
+                'default'
+            );
+        }
+
+        //refresh local cache
+        if ($cleanAppCache) {
+            if ($updateLocalConfig) {
+                $objectManager->get('Magento\Framework\App\Config\ReinitableConfigInterface')->reinit();
+                $objectManager->get('Magento\Store\Model\StoreManagerInterface')->reinitStores();
+            }
+
+            if (!$this->_cleanAppConfigCache()) {
+                throw new \RuntimeException('Application configuration cache cannot be cleaned.');
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Restore config values changed during tests
+     */
+    protected function _restoreAppConfig()
+    {
+        foreach ($this->_origConfigValues as $configPath => $origValue) {
+            $this->_updateAppConfig($configPath, $origValue, true, true);
+        }
+    }
+
+    /**
+     * @param \Exception $e
+     * @return array
+     * <pre> ex.
+     * 'message' => "No such entity with %fieldName1 = %value1, %fieldName2 = %value2"
+     * 'parameters' => [
+     *      "fieldName1" => "email",
+     *      "value1" => "dummy@example.com",
+     *      "fieldName2" => "websiteId",
+     *      "value2" => 0
+     * ]
+     *
+     * </pre>
+     */
+    public function processRestExceptionResult(\Exception $e)
+    {
+        $error = json_decode($e->getMessage(), true);
+        //Remove line breaks and replace with space
+        $error['message'] = trim(preg_replace('/\s+/', ' ', $error['message']));
+        // remove trace and type, will only be present if server is in dev mode
+        unset($error['trace']);
+        unset($error['type']);
+        return $error;
+    }
+
+    /**
+     * Verify that SOAP fault contains necessary information.
+     *
+     * @param \SoapFault $soapFault
+     * @param string $expectedMessage
+     * @param string $expectedFaultCode
+     * @param array $expectedErrorParams
+     * @param array $expectedWrappedErrors
+     * @param string $traceString
+     */
+    protected function checkSoapFault(
+        $soapFault,
+        $expectedMessage,
+        $expectedFaultCode,
+        $expectedErrorParams = [],
+        $expectedWrappedErrors = [],
+        $traceString = null
+    ) {
+        $this->assertContains($expectedMessage, $soapFault->getMessage(), "Fault message is invalid.");
+
+        $errorDetailsNode = 'GenericFault';
+        $errorDetails = isset($soapFault->detail->$errorDetailsNode) ? $soapFault->detail->$errorDetailsNode : null;
+        if (!empty($expectedErrorParams) || !empty($expectedWrappedErrors)) {
+            /** Check SOAP fault details */
+            $this->assertNotNull($errorDetails, "Details must be present.");
+            $this->_checkFaultParams($expectedErrorParams, $errorDetails);
+            $this->_checkWrappedErrors($expectedWrappedErrors, $errorDetails);
+        }
+
+        if ($traceString) {
+            /** Check error trace */
+            $traceNode = Fault::NODE_DETAIL_TRACE;
+            $mode = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\App\State')
+                ->getMode();
+            if ($mode == \Magento\Framework\App\State::MODE_DEVELOPER) {
+                /** Developer mode changes tested behavior and it cannot properly be tested for now */
+                $this->assertContains(
+                    $traceString,
+                    $errorDetails->$traceNode,
+                    'Trace Information is incorrect.'
+                );
+            } else {
+                $this->assertNull($errorDetails, "Details are not expected.");
+            }
+        }
+
+        /** Check SOAP fault code */
+        $this->assertNotNull($soapFault->faultcode, "Fault code must not be empty.");
+        $this->assertEquals($expectedFaultCode, $soapFault->faultcode, "Fault code is invalid.");
+    }
+
+    /**
+     * Check additional error parameters.
+     *
+     * @param array $expectedErrorParams
+     * @param \stdClass $errorDetails
+     */
+    protected function _checkFaultParams($expectedErrorParams, $errorDetails)
+    {
+        $paramsNode = Fault::NODE_DETAIL_PARAMETERS;
+        if ($expectedErrorParams) {
+            $paramNode = Fault::NODE_DETAIL_PARAMETER;
+            $paramKey = Fault::NODE_DETAIL_PARAMETER_KEY;
+            $paramValue = Fault::NODE_DETAIL_PARAMETER_VALUE;
+            $actualParams = [];
+            if (isset($errorDetails->$paramsNode->$paramNode)) {
+                if (is_array($errorDetails->$paramsNode->$paramNode)) {
+                    foreach ($errorDetails->$paramsNode->$paramNode as $param) {
+                        $actualParams[$param->$paramKey] = $param->$paramValue;
+                    }
+                } else {
+                    $param = $errorDetails->$paramsNode->$paramNode;
+                    $actualParams[$param->$paramKey] = $param->$paramValue;
+                }
+            }
+            $this->assertEquals(
+                $expectedErrorParams,
+                $actualParams,
+                "Parameters in fault details are invalid."
+            );
+        } else {
+            $this->assertFalse(isset($errorDetails->$paramsNode), "Parameters are not expected in fault details.");
+        }
+    }
+
+    /**
+     * Check additional wrapped errors.
+     *
+     * @param array $expectedWrappedErrors
+     * @param \stdClass $errorDetails
+     */
+    protected function _checkWrappedErrors($expectedWrappedErrors, $errorDetails)
+    {
+        $wrappedErrorsNode = Fault::NODE_DETAIL_WRAPPED_ERRORS;
+        if ($expectedWrappedErrors) {
+            $wrappedErrorNode = Fault::NODE_DETAIL_WRAPPED_ERROR;
+            $wrappedErrorNodeFieldName = 'fieldName';
+            $wrappedErrorNodeValue = Fault::NODE_DETAIL_WRAPPED_ERROR_VALUE;
+            $actualWrappedErrors = [];
+            if (isset($errorDetails->$wrappedErrorsNode->$wrappedErrorNode)) {
+                if (is_array($errorDetails->$wrappedErrorsNode->$wrappedErrorNode)) {
+                    foreach ($errorDetails->$wrappedErrorsNode->$wrappedErrorNode as $error) {
+                        $actualParameters = [];
+                        foreach ($error->parameters->parameter as $parameter) {
+                            $actualParameters[$parameter->key] = $parameter->value;
+                        }
+                        $actualWrappedErrors[] = [
+                            'message' => $error->message,
+                            'params' => $actualParameters,
+                        ];
+                    }
+                } else {
+                    $error = $errorDetails->$wrappedErrorsNode->$wrappedErrorNode;
+                    $actualWrappedErrors[] = [
+                        "fieldName" => $error->$wrappedErrorNodeFieldName,
+                        "value" => $error->$wrappedErrorNodeValue,
+                    ];
+                }
+            }
+            $this->assertEquals(
+                $expectedWrappedErrors,
+                $actualWrappedErrors,
+                "Wrapped errors in fault details are invalid."
+            );
+        } else {
+            $this->assertFalse(
+                isset($errorDetails->$wrappedErrorsNode),
+                "Wrapped errors are not expected in fault details."
+            );
+        }
+    }
+}
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
new file mode 100644
index 0000000000000000000000000000000000000000..055fa381ae23bb427e1d4c9512158396ce874a32
--- /dev/null
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\TestFramework;
+
+
+/**
+ * Provides access to the application for the tests
+ *
+ * Allows installation and uninstallation
+ */
+class WebApiApplication extends Application
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function run()
+    {
+        throw new \Exception(
+            "Can't start application: purpose of Web API Application is to use classes and models from the application"
+            . " and don't run it"
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function install()
+    {
+        $installOptions = $this->getInstallConfig();
+
+        /* Install application */
+        if ($installOptions) {
+            $installCmd = 'php -f ' . BP . '/setup/index.php install';
+            $installArgs = [];
+            foreach ($installOptions as $optionName => $optionValue) {
+                if (is_bool($optionValue)) {
+                    if (true === $optionValue) {
+                        $installCmd .= " --$optionName";
+                    }
+                    continue;
+                }
+                if (!empty($optionValue)) {
+                    $installCmd .= " --$optionName=%s";
+                    $installArgs[] = $optionValue;
+                }
+            }
+            $this->_shell->execute($installCmd, $installArgs);
+        }
+    }
+
+    /**
+     * Use the application as is
+     *
+     * {@inheritdoc}
+     */
+    protected function getCustomDirs()
+    {
+        return [];
+    }
+}
diff --git a/dev/tests/api-functional/framework/autoload.php b/dev/tests/api-functional/framework/autoload.php
new file mode 100644
index 0000000000000000000000000000000000000000..231e39080884504cd02a427a6333e875d0dae087
--- /dev/null
+++ b/dev/tests/api-functional/framework/autoload.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+require_once __DIR__ . '/../../../../app/autoload.php';
+
+$testsBaseDir = dirname(__DIR__);
+$integrationTestsDir = realpath("{$testsBaseDir}/../integration/");
+
+$autoloadWrapper = \Magento\Framework\Autoload\AutoloaderRegistry::getAutoloader();
+$autoloadWrapper->addPsr4('Magento\\TestFramework\\', "{$testsBaseDir}/framework/Magento/TestFramework/");
+$autoloadWrapper->addPsr4('Magento\\TestFramework\\', "{$integrationTestsDir}/framework/Magento/TestFramework/");
+$autoloadWrapper->addPsr4('Magento\\', "{$testsBaseDir}/testsuite/Magento/");
diff --git a/dev/tests/api-functional/framework/bootstrap.php b/dev/tests/api-functional/framework/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae037a554b21cd9e7529fd5bb320d5ea087b6580
--- /dev/null
+++ b/dev/tests/api-functional/framework/bootstrap.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Autoload\AutoloaderRegistry;
+
+require_once __DIR__ . '/../../../../app/bootstrap.php';
+require_once __DIR__ . '/autoload.php';
+
+$testsBaseDir = dirname(__DIR__);
+$integrationTestsDir = realpath("{$testsBaseDir}/../integration");
+
+$logWriter = new \Zend_Log_Writer_Stream('php://output');
+$logWriter->setFormatter(new \Zend_Log_Formatter_Simple('%message%' . PHP_EOL));
+$logger = new \Zend_Log($logWriter);
+
+/** Copy test modules to app/code/Magento to make them visible for Magento instance */
+$pathToCommittedTestModules = __DIR__ . '/../_files/Magento';
+$pathToInstalledMagentoInstanceModules = __DIR__ . '/../../../../app/code/Magento';
+$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathToCommittedTestModules));
+/** @var SplFileInfo $file */
+foreach ($iterator as $file) {
+    if (!$file->isDir()) {
+        $source = $file->getPathname();
+        $relativePath = substr($source, strlen($pathToCommittedTestModules));
+        $destination = $pathToInstalledMagentoInstanceModules . $relativePath;
+        $targetDir = dirname($destination);
+        if (!is_dir($targetDir)) {
+            mkdir($targetDir, 0755, true);
+        }
+        copy($source, $destination);
+    }
+}
+unset($iterator, $file);
+
+/* Bootstrap the application */
+$settings = new \Magento\TestFramework\Bootstrap\Settings($testsBaseDir, get_defined_constants());
+$shell = new \Magento\Framework\Shell(new \Magento\Framework\Shell\CommandRenderer(), $logger);
+
+$installConfigFile = $settings->getAsConfigFile('TESTS_INSTALL_CONFIG_FILE');
+if (!file_exists($installConfigFile)) {
+    $installConfigFile = $installConfigFile . '.dist';
+}
+$dirList = new \Magento\Framework\App\Filesystem\DirectoryList(BP);
+$application =  new \Magento\TestFramework\WebApiApplication(
+    $shell,
+    $dirList->getPath(DirectoryList::VAR_DIR),
+    $installConfigFile,
+    BP . '/app/etc/',
+    $settings->get('TESTS_MAGENTO_MODE'),
+    AutoloaderRegistry::getAutoloader()
+);
+
+if (defined('TESTS_MAGENTO_INSTALLATION') && TESTS_MAGENTO_INSTALLATION === 'enabled') {
+    if (defined('TESTS_CLEANUP') && TESTS_CLEANUP === 'enabled') {
+        $application->cleanup();
+    }
+    $application->install();
+}
+
+$bootstrap = new \Magento\TestFramework\Bootstrap(
+    $settings,
+    new \Magento\TestFramework\Bootstrap\Environment(),
+    new \Magento\TestFramework\Bootstrap\WebapiDocBlock("{$integrationTestsDir}/testsuite"),
+    new \Magento\TestFramework\Bootstrap\Profiler(new \Magento\Framework\Profiler\Driver\Standard()),
+    $shell,
+    $application,
+    new \Magento\TestFramework\Bootstrap\MemoryFactory($shell)
+);
+$bootstrap->runBootstrap();
+$application->initialize();
+
+\Magento\TestFramework\Helper\Bootstrap::setInstance(new \Magento\TestFramework\Helper\Bootstrap($bootstrap));
+\Magento\Framework\Test\Utility\Files::setInstance(new \Magento\Framework\Test\Utility\Files(BP));
+unset($bootstrap, $application, $settings, $shell);
diff --git a/dev/tests/api-functional/phpunit.xml.dist b/dev/tests/api-functional/phpunit.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..b885beab08ed0fbbbaf06705775f250543ef32d6
--- /dev/null
+++ b/dev/tests/api-functional/phpunit.xml.dist
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * PHPUnit configuration for Web API functional tests.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+         colors="true"
+         bootstrap="./framework/bootstrap.php"
+>
+    <!-- Test suites definition -->
+    <testsuites>
+        <testsuite name="Magento Web API Functional Tests">
+            <directory suffix="Test.php">testsuite</directory>
+        </testsuite>
+    </testsuites>
+
+    <!-- Code coverage filters -->
+    <filter>
+        <whitelist>
+            <!-- All CE modules -->
+            <directory suffix=".php">../../app/code/Magento</directory>
+            <exclude>
+                <!-- Excluding installation and upgrade scripts -->
+                <directory>../../app/code/Magento/*/sql</directory>
+                <!-- Excluding data installation and upgrade scripts -->
+                <directory>../../app/code/Magento/*/data</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+
+    <!-- PHP INI settings and constants definition -->
+    <php>
+        <includePath>./testsuite</includePath>
+        <const name="TESTS_INSTALL_CONFIG_FILE" value="config/install-config-mysql.php"/>
+        <!-- WebSerivice Type. Possible values: soap, rest -->
+        <const name="TESTS_WEB_API_ADAPTER" value="rest"/>
+        <!-- Webserver URL -->
+        <const name="TESTS_BASE_URL" value="http://magento.url"/>
+        <!-- Webserver API user -->
+        <const name="TESTS_WEBSERVICE_USER" value="admin"/>
+        <!-- Webserver API key -->
+        <const name="TESTS_WEBSERVICE_APIKEY" value="123123q"/>
+        <!-- Define if debugger should be started using XDEBUG_SESSION cookie -->
+        <const name="TESTS_XDEBUG_ENABLED" value="false"/>
+        <!-- Define XDEBUG_SESSION cookie value-->
+        <const name="TESTS_XDEBUG_SESSION" value="phpstorm" />
+        <!--Generate documentation from REST tests and put it into var/log/rest-documentation directory-->
+        <const name="GENERATE_REST_DOCUMENTATION" value="false" />
+
+        <ini name="date.timezone" value="America/Los_Angeles"/>
+        <ini name="soap.wsdl_cache_enabled" value="0" />
+
+        <!-- Semicolon-separated 'glob' patterns, that match global XML configuration files -->
+        <const name="TESTS_GLOBAL_CONFIG_DIR" value="../../../app/etc"/>
+        <!-- Whether to cleanup the application before running tests or not -->
+        <const name="TESTS_CLEANUP" value="enabled"/>
+        <!--Defines if Magento should be installed before tests execution-->
+        <const name="TESTS_MAGENTO_INSTALLATION" value="disabled"/>
+        <!-- Magento mode for tests execution. Possible values are "default", "developer" and "production". -->
+        <const name="TESTS_MAGENTO_MODE" value="default"/>
+    </php>
+
+    <!-- Test listeners -->
+    <listeners>
+        <listener class="Magento\TestFramework\Event\PhpUnit"/>
+    </listeners>
+</phpunit>
diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductLinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductLinkManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..078d61a66d8e91ed7b55c2c8414e5942c4b26f03
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductLinkManagementTest.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Bundle\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Model\Rest\Config;
+
+class ProductLinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'bundleProductLinkManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/bundle-products';
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testGetChildren()
+    {
+        $productSku = 'bundle-product';
+        $expected = [
+            [
+                'sku' => 'simple',
+                'position' => 0,
+                'qty' => 1,
+            ],
+        ];
+
+        $result = $this->getChildren($productSku);
+
+        $this->assertArrayHasKey(0, $result);
+        $this->assertArrayHasKey('option_id', $result[0]);
+        $this->assertArrayHasKey('is_default', $result[0]);
+        $this->assertArrayHasKey('is_defined', $result[0]);
+        $this->assertArrayHasKey('price', $result[0]);
+        $this->assertArrayHasKey('price_type', $result[0]);
+
+        unset($result[0]['option_id'], $result[0]['is_default'], $result[0]['is_defined']);
+        unset($result[0]['price'], $result[0]['price_type']);
+
+        ksort($result[0]);
+        ksort($expected[0]);
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testRemoveChild()
+    {
+        $productSku = 'bundle-product';
+        $childSku = 'simple';
+        $optionIds = $this->getProductOptions(3);
+        $optionId = array_shift($optionIds);
+        $this->assertTrue($this->removeChild($productSku, $optionId, $childSku));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php
+     */
+    public function testAddChild()
+    {
+        $productSku = 'bundle-product';
+        $children = $this->getChildren($productSku);
+
+        $optionId = $children[0]['option_id'];
+
+        $linkedProduct = [
+            'sku' => 'virtual-product',
+            'option_id' => $optionId,
+            'position' => '1',
+            'is_default' => 1,
+            'priceType' => 2,
+            'price' => 151.34,
+            'qty' => 8,
+            'can_change_quantity' => 1,
+        ];
+
+        $childId = $this->addChild($productSku, $optionId, $linkedProduct);
+        $this->assertGreaterThan(0, $childId);
+    }
+
+    /**
+     * @param string $productSku
+     * @param int $optionId
+     * @param array $linkedProduct
+     * @return string
+     */
+    private function addChild($productSku, $optionId, $linkedProduct)
+    {
+        $resourcePath = self::RESOURCE_PATH . '/:productSku/links/:optionId';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => str_replace(
+                    [':productSku', ':optionId'],
+                    [$productSku, $optionId],
+                    $resourcePath
+                ),
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'AddChildByProductSku',
+            ],
+        ];
+        return $this->_webApiCall(
+            $serviceInfo,
+            ['productSku' => $productSku, 'optionId' => $optionId, 'linkedProduct' => $linkedProduct]
+        );
+    }
+
+    protected function getProductOptions($productId)
+    {
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Product');
+        $product->load($productId);
+        /** @var  \Magento\Bundle\Model\Product\Type $type */
+        $type = Bootstrap::getObjectManager()->get('Magento\Bundle\Model\Product\Type');
+        return $type->getOptionsIds($product);
+    }
+
+    protected function removeChild($productSku, $optionId, $childSku)
+    {
+        $resourcePath = self::RESOURCE_PATH . '/%s/option/%s/child/%s';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => sprintf($resourcePath, $productSku, $optionId, $childSku),
+                'httpMethod' => Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'removeChild',
+            ],
+        ];
+        $requestData = ['productSku' => $productSku, 'optionId' => $optionId, 'childSku' => $childSku];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @param string $productSku
+     * @return string
+     */
+    protected function getChildren($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/children',
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getChildren',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['productId' => $productSku]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b35e1c4ff5be9dab24c6cc24b26eac6fad91cbd
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php
@@ -0,0 +1,267 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Bundle\Api;
+
+use Magento\Webapi\Model\Rest\Config;
+
+class ProductOptionRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'bundleProductOptionRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/bundle-products/:productSku/option';
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testGet()
+    {
+        $productSku = 'bundle-product';
+        $expected = [
+            'required' => true,
+            'position' => 0,
+            'type' => 'select',
+            'title' => 'Bundle Product Items',
+            'sku' => $productSku,
+            'product_links' => [
+                [
+                    'sku' => 'simple',
+                    'qty' => 1,
+                    'position' => 0,
+                    'is_defined' => true,
+                    'is_default' => false,
+                    'price' => null,
+                    'price_type' => null,
+                ],
+            ],
+        ];
+        $optionId = $this->getList($productSku)[0]['option_id'];
+        $result = $this->get($productSku, $optionId);
+
+        $this->assertArrayHasKey('option_id', $result);
+        $expected['product_links'][0]['option_id'] = $result['option_id'];
+        unset($result['option_id']);
+
+        ksort($expected);
+        ksort($result);
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testGetList()
+    {
+        $productSku = 'bundle-product';
+        $expected = [
+            [
+                'required' => true,
+                'position' => 0,
+                'type' => 'select',
+                'title' => 'Bundle Product Items',
+                'sku' => $productSku,
+                'product_links' => [
+                    [
+                        'sku' => 'simple',
+                        'qty' => 1,
+                        'position' => 0,
+                        'is_defined' => true,
+                        'is_default' => false,
+                        'price' => null,
+                        'price_type' => null,
+                    ],
+                ],
+            ],
+        ];
+        $result = $this->getList($productSku);
+
+        $this->assertArrayHasKey(0, $result);
+        $this->assertArrayHasKey('option_id', $result[0]);
+        $expected[0]['product_links'][0]['option_id'] = $result[0]['option_id'];
+        unset($result[0]['option_id']);
+
+        ksort($expected[0]);
+        ksort($result[0]);
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testRemove()
+    {
+        $productSku = 'bundle-product';
+
+        $optionId = $this->getList($productSku)[0]['option_id'];
+        $result = $this->remove($productSku, $optionId);
+
+        $this->assertTrue($result);
+
+        try {
+            $this->get($productSku, $optionId);
+        } catch (\Exception $e) {
+            throw new \Magento\Framework\Exception\NoSuchEntityException();
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testAdd()
+    {
+        $productSku = 'bundle-product';
+        $request = [
+            'required' => true,
+            'position' => 0,
+            'type' => 'select',
+            'title' => 'test product',
+            'product_links' => [],
+            'sku' => $productSku,
+        ];
+
+        $optionId = $this->add($request);
+        $this->assertGreaterThan(0, $optionId);
+        $result = $this->get($productSku, $optionId);
+
+        $this->assertArrayHasKey('option_id', $result);
+        $this->assertArrayHasKey('sku', $result);
+        unset($result['option_id']);
+
+        ksort($result);
+        ksort($request);
+        $this->assertEquals($request, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Bundle/_files/product.php
+     */
+    public function testUpdate()
+    {
+        $productSku = 'bundle-product';
+        $request = [
+            'title' => 'someTitle',
+            'sku' => $productSku,
+        ];
+
+        $optionId = $this->getList($productSku)[0]['option_id'];
+        $result = $this->update($optionId, $request);
+
+        $this->assertEquals($result, $optionId);
+
+        $result = $this->get($productSku, $optionId);
+
+        $this->assertCount(7, $result);
+        $this->assertArrayHasKey('title', $result);
+        $this->assertEquals($request['title'], $result['title']);
+    }
+
+    /**
+     * @param int $optionId
+     * @param array $option
+     * @return string
+     */
+    protected function update($optionId, $option)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/bundle-products/option/' . $optionId,
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'bundleProductOptionManagementV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'bundleProductOptionManagementV1Save',
+            ],
+        ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $option['optionId'] = $optionId;
+        }
+        return $this->_webApiCall($serviceInfo, ['option' => $option]);
+    }
+
+    /**
+     * @param array $option
+     * @return string
+     */
+    protected function add($option)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/bundle-products/option/add',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'bundleProductOptionManagementV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'bundleProductOptionManagementV1Save',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['option' => $option]);
+    }
+
+    /**
+     * @param string $productSku
+     * @param int $optionId
+     * @return string
+     */
+    protected function remove($productSku, $optionId)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => str_replace(':productSku', $productSku, self::RESOURCE_PATH) . '/' . $optionId,
+                'httpMethod' => Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'optionId' => $optionId]);
+    }
+
+    /**
+     * @param string $productSku
+     * @return string
+     */
+    protected function getList($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => str_replace(':productSku', $productSku, self::RESOURCE_PATH) . '/all',
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+    }
+
+    /**
+     * @param string $productSku
+     * @param int $optionId
+     * @return string
+     */
+    protected function get($productSku, $optionId)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => str_replace(':productSku', $productSku, self::RESOURCE_PATH) . '/' . $optionId,
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'optionId' => $optionId]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionTypeListTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionTypeListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d4be9a704ce9e18608f3476b7cafb1b6f7afd80
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionTypeListTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Bundle\Api;
+
+use Magento\Webapi\Model\Rest\Config;
+
+class ProductOptionTypeListTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_READ_NAME = 'bundleProductOptionTypeListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/bundle-products/option/types';
+
+    public function testGetTypes()
+    {
+        $expected = [
+            ['label' => 'Drop-down', 'code' => 'select'],
+            ['label' => 'Radio Buttons', 'code' => 'radio'],
+            ['label' => 'Checkbox', 'code' => 'checkbox'],
+            ['label' => 'Multiple Select', 'code' => 'multi'],
+        ];
+        $result = $this->getTypes();
+
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * @return string
+     */
+    protected function getTypes()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getItems',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..68db7d521095ae798280dfd5ede1e4dd5b095059
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductServiceTest.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Bundle\Api;
+
+use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\Framework\Api\AbstractExtensibleObject;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class ProductServiceTest for testing Bundle Product API
+ */
+class ProductServiceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products';
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Product\Collection
+     */
+    protected $productCollection;
+
+    /**
+     * Execute per test initialization
+     */
+    public function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->productCollection = $objectManager->get('Magento\Catalog\Model\Resource\Product\Collection');
+    }
+
+    /**
+     * Execute per test cleanup
+     */
+    public function tearDown()
+    {
+        /** @var \Magento\Framework\Registry $registry */
+        $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', true);
+
+        $this->productCollection->addFieldToFilter(
+            'sku',
+            ['in' => ['sku-test-product-bundle']]
+        )->delete();
+        unset($this->productCollection);
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', false);
+        parent::tearDown();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_new.php
+     */
+    public function testCreateBundle()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $bundleProductOptions = [
+            "attribute_code" => "bundle_product_options",
+            "value" => [
+                [
+                    "title" => "test option",
+                    "type" => "checkbox",
+                    "required" => 1,
+                    "product_links" => [
+                        [
+                            "sku" => 'simple',
+                            "qty" => 1,
+                        ],
+                    ],
+                ],
+            ],
+        ];
+
+        $uniqueId = 'sku-test-product-bundle';
+        $product = [
+            "sku" => $uniqueId,
+            "name" => $uniqueId,
+            "type_id" => "bundle",
+            "price" => 50,
+            'attribute_set_id' => 4,
+            "custom_attributes" => [
+                "price_type" => [
+                    'attribute_code' => 'price_type',
+                    'value' => \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC
+                ],
+                "bundle_product_options" => $bundleProductOptions,
+                "price_view" => [
+                    "attribute_code" => "price_view",
+                    "value" => "test",
+                ],
+            ],
+        ];
+
+        $response = $this->createProduct($product);
+
+        $this->assertEquals($uniqueId, $response[ProductInterface::SKU]);
+        $this->assertEquals(
+            $bundleProductOptions,
+            $response[AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY]["bundle_product_options"]
+        );
+
+        $response = $this->getProduct($uniqueId);
+        $foundBundleProductOptions = false;
+        foreach ($response[AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY] as $customAttribute) {
+            if ($customAttribute["attribute_code"] === 'bundle_product_options') {
+                $this->assertEquals('simple', $customAttribute["value"][0]["product_links"][0]["sku"]);
+                $foundBundleProductOptions = true;
+            }
+        }
+        $this->assertTrue($foundBundleProductOptions);
+    }
+
+    /**
+     * Get product
+     *
+     * @param string $productSku
+     * @return array the product data
+     */
+    protected function getProduct($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $response = (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ?
+            $this->_webApiCall($serviceInfo, ['productSku' => $productSku]) : $this->_webApiCall($serviceInfo);
+
+        return $response;
+    }
+
+    /**
+     * Create product
+     *
+     * @param array $product
+     * @return array the created product data
+     */
+    protected function createProduct($product)
+    {
+        $serviceInfo = [
+            'rest' => ['resourcePath' => self::RESOURCE_PATH, 'httpMethod' => RestConfig::HTTP_METHOD_POST],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = ['product' => $product];
+        $response = $this->_webApiCall($serviceInfo, $requestData);
+        $product[ProductInterface::SKU] = $response[ProductInterface::SKU];
+        return $product;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..34dd1076b8843813b129b1e22f93027eec34b1f2
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php
@@ -0,0 +1,221 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class AttributeSetManagementTest extends WebapiAbstract
+{
+    /**
+     * @var array
+     */
+    private $createServiceInfo;
+
+    protected function setUp()
+    {
+        $this->createServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetManagementV1Create',
+            ],
+        ];
+    }
+
+    public function testCreate()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 500,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $result = $this->_webApiCall($this->createServiceInfo, $arguments);
+        $this->assertNotNull($result);
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $this->assertNotNull($attributeSet);
+        $this->assertEquals($attributeSet->getId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $entityType->getId());
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+        $this->assertEquals($attributeSet->getSortOrder(), 500);
+
+        // Clean up database
+        $attributeSet->delete();
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid value
+     */
+    public function testCreateThrowsExceptionIfGivenAttributeSetAlreadyHasId()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_id' => 1,
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 100,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Can not create attribute set based on not existing attribute set
+     */
+    public function testCreateThrowsExceptionIfGivenSkeletonIdIsInvalid()
+    {
+        $attributeSetName = 'new_attribute_set';
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 200,
+            ],
+            'skeletonId' => 0,
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Can not create attribute set based on non product attribute set.
+     */
+    public function testCreateThrowsExceptionIfGivenSkeletonIdHasWrongEntityType()
+    {
+        $attributeSetName = 'new_attribute_set';
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 200,
+            ],
+            'skeletonId' => 7,
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Can not create attribute set based on not existing attribute set
+     */
+    public function testCreateThrowsExceptionIfGivenSkeletonAttributeSetDoesNotExist()
+    {
+        $attributeSetName = 'new_attribute_set';
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 300,
+            ],
+            'skeletonId' => 9999,
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Attribute set name is empty.
+     */
+    public function testCreateThrowsExceptionIfAttributeSetNameIsEmpty()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = '';
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 500,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    public function testCreateThrowsExceptionIfAttributeSetWithGivenNameAlreadyExists()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'Default';
+        $expectedMessage = 'An attribute set with the "Default" name already exists.';
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 550,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+
+        try {
+            $this->_webApiCall($this->createServiceInfo, $arguments);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals(
+                $expectedMessage,
+                $errorObj['message']
+            );
+            $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        }
+    }
+
+    /**
+     * Retrieve attribute set based on given name.
+     * This utility methods assumes that there is only one attribute set with given name,
+     *
+     * @param string $attributeSetName
+     * @return \Magento\Eav\Model\Entity\Attribute\Set|null
+     */
+    protected function getAttributeSetByName($attributeSetName)
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
+        $attributeSet = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Set')
+            ->load($attributeSetName, 'attribute_set_name');
+        if ($attributeSet->getId() === null) {
+            return null;
+        }
+        return $attributeSet;
+    }
+
+    /**
+     * Retrieve entity type based on given code.
+     *
+     * @param string $entityTypeCode
+     * @return \Magento\Eav\Model\Entity\Type|null
+     */
+    protected function getEntityTypeByCode($entityTypeCode)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Type $entityType */
+        $entityType = $objectManager->create('Magento\Eav\Model\Config')
+            ->getEntityType($entityTypeCode);
+        return $entityType;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b2bb1d5b2e74b2b9f3bc0cb3efd387dc4731fdf
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class AttributeSetRepositoryTest extends WebapiAbstract
+{
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testGet()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $attributeSetId = $attributeSet->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1Get',
+            ],
+        ];
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $result = $this->_webApiCall($serviceInfo, $arguments);
+        $this->assertNotNull($result);
+        $this->assertEquals($attributeSet->getId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testGetThrowsExceptionIfRequestedAttributeSetDoesNotExist()
+    {
+        $attributeSetId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1Get',
+            ],
+        ];
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->_webApiCall($serviceInfo, $arguments);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testSave()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/' . $attributeSet->getId(),
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1Save',
+            ],
+        ];
+
+        $updatedSortOrder = $attributeSet->getSortOrder() + 200;
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_id' => $attributeSet->getId(),
+                // name is the same, because it is used by fixture rollback script
+                'attribute_set_name' => $attributeSet->getAttributeSetName(),
+                'entity_type_id' => $attributeSet->getEntityTypeId(),
+                'sort_order' => $updatedSortOrder,
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $arguments);
+        $this->assertNotNull($result);
+        // Reload attribute set data
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $this->assertEquals($attributeSet->getAttributeSetId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($updatedSortOrder, $result['sort_order']);
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testDeleteById()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $attributeSetId = $attributeSet->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1DeleteById',
+            ],
+        ];
+
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $arguments));
+        $this->assertNull($this->getAttributeSetByName($attributeSetName));
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testDeleteByIdThrowsExceptionIfRequestedAttributeSetDoesNotExist()
+    {
+        $attributeSetId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1DeleteById',
+            ],
+        ];
+
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->_webApiCall($serviceInfo, $arguments);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'entity_type_code',
+                                'value' => 'catalog_product',
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/attribute-sets/sets/list',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'catalogAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogAttributeSetRepositoryV1GetList',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['attribute_set_id']);
+        $this->assertNotNull($response['items'][0]['attribute_set_name']);
+    }
+
+    /**
+     * Retrieve attribute set based on given name.
+     * This utility methods assumes that there is only one attribute set with given name,
+     *
+     * @param string $attributeSetName
+     * @return \Magento\Eav\Model\Entity\Attribute\Set|null
+     */
+    protected function getAttributeSetByName($attributeSetName)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
+        $attributeSet = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Set')
+            ->load($attributeSetName, 'attribute_set_name');
+        if ($attributeSet->getId() === null) {
+            return null;
+        }
+        return $attributeSet;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeOptionManagementInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7540f1b3a348f62e6a78ffb45241aeedb536e3b
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeOptionManagementInterfaceTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class CategoryAttributeOptionManagementInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogCategoryAttributeOptionManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/categories/attributes';
+
+    public function testGetItems()
+    {
+        $testAttributeCode = 'include_in_menu';
+        $expectedOptions = [
+            [
+                    'label' => 'Yes',
+                    'value' => '1',
+            ],
+            [
+                    'label' => 'No',
+                    'value' => '0',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getItems',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, ['attributeCode' => $testAttributeCode]);
+
+        $this->assertTrue(is_array($response));
+        $this->assertEquals($expectedOptions, $response);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a206507971116cb7118c717cd822923e29e2c058
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryAttributeRepositoryTest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class CategoryAttributeRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogCategoryAttributeRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/categories/attributes';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category_attribute.php
+     */
+    public function testGet()
+    {
+        $attributeCode = 'test_attribute_code_666';
+        $attribute = $this->getAttribute($attributeCode);
+
+        $this->assertTrue(is_array($attribute));
+        $this->assertArrayHasKey('attribute_id', $attribute);
+        $this->assertArrayHasKey('attribute_code', $attribute);
+        $this->assertEquals($attributeCode, $attribute['attribute_code']);
+    }
+
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'frontend_input',
+                                'value' => 'text',
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+            'entityTypeCode' => \Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE,
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['default_frontend_label']);
+        $this->assertNotNull($response['items'][0]['attribute_id']);
+    }
+
+    /**
+     * @param $attributeCode
+     * @return array|bool|float|int|string
+     */
+    protected function getAttribute($attributeCode)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeCode,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['attributeCode' => $attributeCode]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc64e880b646e0110d17ff9a46808fe372206385
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkManagementTest.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+class CategoryLinkManagementTest extends WebapiAbstract
+{
+    const SERVICE_WRITE_NAME = 'catalogCategoryLinkManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH_SUFFIX = '/V1/categories';
+    const RESOURCE_PATH_PREFIX = 'products';
+
+    private $modelId = 333;
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category_product.php
+     */
+    public function testAssignedProducts()
+    {
+        $expected = [
+            [
+                'sku' => 'simple333',
+                'position' => '1',
+                'category_id' => '333',
+            ],
+        ];
+        $result = $this->getAssignedProducts($this->modelId);
+
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testInfoNoSuchEntityException()
+    {
+        try {
+            $this->getAssignedProducts(-1);
+        } catch (\Exception $e) {
+            $this->assertContains('No such entity with %fieldName = %fieldValue', $e->getMessage());
+        }
+    }
+
+    /**
+     * @param int $id category id
+     * @return string
+     */
+    protected function getAssignedProducts($id)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_SUFFIX . '/' . $id . '/' . self::RESOURCE_PATH_PREFIX,
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_WRITE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_WRITE_NAME . 'GetAssignedProducts',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['categoryId' => $id]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..99ecffa03a07c598cb5f94e11fcd00b0fafb5b9f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryLinkRepositoryTest.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+class CategoryLinkRepositoryTest extends WebapiAbstract
+{
+    const SERVICE_WRITE_NAME = 'catalogCategoryLinkRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH_SUFFIX = '/V1/categories';
+    const RESOURCE_PATH_PREFIX = 'products';
+
+    private $categoryId = 333;
+
+    /**
+     * @dataProvider saveDataProvider
+     * @magentoApiDataFixture Magento/Catalog/_files/products_in_category.php
+     * @param int $productId
+     * @param string[] $productLink
+     * @param int $productPosition
+     */
+    public function testSave($productLink, $productId, $productPosition = 0)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_SUFFIX
+                    . '/' . $this->categoryId . '/' . self::RESOURCE_PATH_PREFIX,
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_WRITE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_WRITE_NAME . 'Save',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['productLink' => $productLink]);
+        $this->assertTrue($result);
+        $this->assertTrue($this->isProductInCategory($this->categoryId, $productId, $productPosition));
+    }
+
+    public function saveDataProvider()
+    {
+        return [
+            [
+                ['sku' => 'simple_with_cross', 'position' => 7, 'category_id' => $this->categoryId],
+                334,
+                7,
+            ],
+            [
+                ['sku' => 'simple_with_cross', 'category_id' => $this->categoryId],
+                334,
+                0
+            ],
+        ];
+    }
+
+    /**
+     * @dataProvider updateProductProvider
+     * @magentoApiDataFixture Magento/Catalog/_files/products_in_category.php
+     * @param int $productId
+     * @param string[] $productLink
+     * @param int $productPosition
+     */
+    public function testUpdateProduct($productLink, $productId, $productPosition = 0)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_SUFFIX
+                    . '/' . $this->categoryId . '/' . self::RESOURCE_PATH_PREFIX,
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_WRITE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_WRITE_NAME . 'Save',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['productLink' => $productLink]);
+        $this->assertTrue($result);
+        $this->assertFalse($this->isProductInCategory($this->categoryId, $productId, $productPosition));
+    }
+
+    public function updateProductProvider()
+    {
+        return [
+            [
+                ['sku' => 'simple_with_cross', 'position' => 7, 'categoryId' => $this->categoryId],
+                333,
+                4,
+            ],
+            [
+                ['sku' => 'simple_with_cross', 'categoryId' => $this->categoryId],
+                333,
+                0
+            ],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_in_category.php
+     */
+    public function testDelete()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_SUFFIX . '/' . $this->categoryId .
+                    '/' . self::RESOURCE_PATH_PREFIX . '/simple',
+                'httpMethod' => Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_WRITE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_WRITE_NAME . 'DeleteByIds',
+            ],
+        ];
+        $result = $this->_webApiCall(
+            $serviceInfo,
+            ['productSku' => 'simple', 'categoryId' => $this->categoryId]
+        );
+        $this->assertTrue($result);
+        $this->assertFalse($this->isProductInCategory($this->categoryId, 333, 10));
+    }
+
+    /**
+     * @param int $categoryId
+     * @param int $productId
+     * @param int $productPosition
+     * @return bool
+     */
+    private function isProductInCategory($categoryId, $productId, $productPosition)
+    {
+        /** @var \Magento\Catalog\Api\CategoryRepositoryInterface $categoryLoader */
+        $categoryLoader = Bootstrap::getObjectManager()->create('Magento\Catalog\Api\CategoryRepositoryInterface');
+        $category = $categoryLoader->get($categoryId);
+        $productsPosition = $category->getProductsPosition();
+
+        if (isset($productsPosition[$productId]) && $productsPosition[$productId] == $productPosition) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eaa58bae0e501b3fcaed3a062d3dbed85361c48b
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryManagementTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\ObjectManager;
+
+class CategoryManagementTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/categories';
+
+    const SERVICE_NAME = 'catalogCategoryManagementV1';
+
+    /**
+     * @dataProvider treeDataProvider
+     * @magentoApiDataFixture Magento/Catalog/_files/category_tree.php
+     */
+    public function testTree($rootCategoryId, $depth, $expectedLevel, $expectedId)
+    {
+        $requestData = ['rootCategoryId' => $rootCategoryId, 'depth' => $depth];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'GetTree'
+            ]
+        ];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+
+        for($i = 0; $i < $expectedLevel; $i++) {
+            $result = $result['children_data'][0];
+        }
+        $this->assertEquals($expectedId, $result['id']);
+        $this->assertEmpty($result['children_data']);
+    }
+
+    public function treeDataProvider()
+    {
+        return [
+            [2, 100, 3, 402],
+            [2, null, 3, 402],
+            [400, 1, 1, 401],
+            [401, 0, 0, 401],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category_tree.php
+     * @dataProvider updateMoveDataProvider
+     */
+    public function testUpdateMove($categoryId, $parentId, $afterId, $expectedPosition)
+    {
+        $expectedPath = '1/2/400/' . $categoryId;
+        $categoryData = ['categoryId' => $categoryId, 'parentId' => $parentId, 'afterId' => $afterId];
+        $serviceInfo =
+            [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH . '/' . $categoryId . '/move',
+                    'httpMethod' => Config::HTTP_METHOD_PUT
+                ],
+                'soap' => [
+                    'service' => self::SERVICE_NAME,
+                    'serviceVersion' => 'V1',
+                    'operation' => self::SERVICE_NAME . 'Move'
+                ]
+            ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $categoryData));
+        /** @var \Magento\Catalog\Model\Category $model */
+        $readService = Bootstrap::getObjectManager()->create('Magento\Catalog\Api\CategoryRepositoryInterface');
+        $model = $readService->get($categoryId);
+        $this->assertEquals($expectedPath, $model->getPath());
+        $this->assertEquals($expectedPosition, $model->getPosition());
+        $this->assertEquals($parentId, $model->getParentId());
+    }
+
+    public function updateMoveDataProvider()
+    {
+        return [
+            [402, 400, null, 2],
+            [402, 400, 401, 2],
+            [402, 400, 999, 2],
+            [402, 400, 0, 1]
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a6a2a5d9efe59c57b0ff284aea06e64b04dd07ce
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php
@@ -0,0 +1,253 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+class CategoryRepositoryTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/categories';
+    const SERVICE_NAME = 'catalogCategoryRepositoryV1';
+
+    private $modelId = 333;
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category_backend.php
+     */
+    public function testGet()
+    {
+        $expected = [
+            'parent_id' => 2,
+            'path' => '1/2/3',
+            'position' => 1,
+            'level' => 2,
+            'available_sort_by' => ['position', 'name'],
+            'include_in_menu' => true,
+            'name' => 'Category 1',
+            'id' => 333,
+            'is_active' => true,
+        ];
+
+        $result = $this->getInfoCategory($this->modelId);
+
+        $this->assertArrayHasKey('created_at', $result);
+        $this->assertArrayHasKey('updated_at', $result);
+        $this->assertArrayHasKey('children', $result);
+        unset($result['created_at'], $result['updated_at'], $result['children']);
+        ksort($expected);
+        ksort($result);
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testInfoNoSuchEntityException()
+    {
+        try {
+            $this->getInfoCategory(-1);
+        } catch (\Exception $e) {
+            $this->assertContains('No such entity with %fieldName = %fieldValue', $e->getMessage());
+        }
+    }
+
+    /**
+     * @param int $id
+     * @return string
+     */
+    protected function getInfoCategory($id)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $id,
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['categoryId' => $id]);
+    }
+    /**
+     * @return array
+     */
+    public function categoryCreationProvider()
+    {
+        return [
+            [
+                $this->getSimpleCategoryData(
+                    [
+                        'name' => 'Test Category Name',
+                    ]
+                ),
+            ]
+        ];
+    }
+
+    /**
+     * Test for create category process
+     *
+     * @magentoApiDataFixture Magento/Catalog/Model/Category/_files/service_category_create.php
+     * @dataProvider categoryCreationProvider
+     */
+    public function testCreate($category)
+    {
+        $category = $this->createCategory($category);
+        $this->assertGreaterThan(0, $category['id']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category.php
+     */
+    public function testDelete()
+    {
+        $this->assertTrue($this->deleteCategory($this->modelId));
+    }
+
+    public function testDeleteNoSuchEntityException()
+    {
+        try {
+            $this->deleteCategory(-1);
+        } catch (\Exception $e) {
+            $this->assertContains('No such entity with %fieldName = %fieldValue', $e->getMessage());
+        }
+    }
+
+    /**
+     * @dataProvider deleteSystemOrRootDataProvider
+     * @expectedException \Exception
+     */
+    public function testDeleteSystemOrRoot()
+    {
+        $this->deleteCategory($this->modelId);
+    }
+
+    public function deleteSystemOrRootDataProvider()
+    {
+        return [
+            [\Magento\Catalog\Model\Category::TREE_ROOT_ID],
+            [2] //Default root category
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/category.php
+     */
+    public function testUpdate()
+    {
+        $categoryId = 333;
+        $categoryData = [
+            'name' => "Update Category Test",
+            'custom_attributes' => [
+                [
+                    'attribute_code' => 'description',
+                    'value' => "Update Category Description Test",
+                ],
+            ],
+        ];
+        $result = $this->updateCategory($categoryId, $categoryData);
+        $this->assertEquals($categoryId, $result['id']);
+        /** @var \Magento\Catalog\Model\Category $model */
+        $model = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\Category');
+        $category = $model->load($categoryId);
+        $this->assertEquals("Update Category Test", $category->getName());
+        $this->assertEquals("Update Category Description Test", $category->getDescription());
+    }
+
+    protected function getSimpleCategoryData($categoryData = [])
+    {
+        return [
+            'path' => '2',
+            'parent_id' => '2',
+            'name' => isset($categoryData['name'])
+                ? $categoryData['name'] : uniqid('Category-', true),
+            'is_active' => '1',
+            'custom_attributes' => [
+                ['attribute_code' => 'url_key', 'value' => ''],
+                ['attribute_code' => 'description', 'value' => 'Custom description'],
+                ['attribute_code' => 'meta_title', 'value' => ''],
+                ['attribute_code' => 'meta_keywords', 'value' => ''],
+                ['attribute_code' => 'meta_description', 'value' => ''],
+                ['attribute_code' => 'include_in_menu', 'value' => '1'],
+                ['attribute_code' => 'display_mode', 'value' => 'PRODUCTS'],
+                ['attribute_code' => 'landing_page', 'value' => ''],
+                ['attribute_code' => 'is_anchor', 'value' => '0'],
+                ['attribute_code' => 'custom_use_parent_settings', 'value' => '0'],
+                ['attribute_code' => 'custom_apply_to_products', 'value' => '0'],
+                ['attribute_code' => 'custom_design', 'value' => ''],
+                ['attribute_code' => 'custom_design_from', 'value' => ''],
+                ['attribute_code' => 'custom_design_to', 'value' => ''],
+                ['attribute_code' => 'page_layout', 'value' => ''],
+            ]
+        ];
+    }
+
+    /**
+     * Create category process
+     *
+     * @param  $category
+     * @return int
+     */
+    protected function createCategory($category)
+    {
+        $serviceInfo = [
+            'rest' => ['resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Config::HTTP_METHOD_POST],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = ['category' => $category];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @param int $id
+     * @return bool
+     * @throws \Exception
+     */
+    protected function deleteCategory($id)
+    {
+        $serviceInfo =
+            [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH . '/' . $id,
+                    'httpMethod' => Config::HTTP_METHOD_DELETE,
+                ],
+                'soap' => [
+                    'service' => self::SERVICE_NAME,
+                    'serviceVersion' => 'V1',
+                    'operation' => self::SERVICE_NAME . 'DeleteByIdentifier',
+                ],
+            ];
+        return $this->_webApiCall($serviceInfo, ['categoryId' => $id]);
+    }
+
+    protected function updateCategory($id, $data)
+    {
+        $serviceInfo =
+            [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH . '/' . $id,
+                    'httpMethod' => Config::HTTP_METHOD_PUT,
+                ],
+                'soap' => [
+                    'service' => self::SERVICE_NAME,
+                    'serviceVersion' => 'V1',
+                    'operation' => self::SERVICE_NAME . 'Save',
+                ],
+            ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $data['id'] = $id;
+            return $this->_webApiCall($serviceInfo, ['id' => $id, 'category' => $data]);
+        } else {
+            return $this->_webApiCall($serviceInfo, ['category' => $data]);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeGroupRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeGroupRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..daf34f578a9bd3947ed0622d0790eb2a8e2023a0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeGroupRepositoryTest.php
@@ -0,0 +1,191 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductAttributeGroupRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductAttributeGroupRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/attribute-sets';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/empty_attribute_group.php
+     */
+    public function testCreateGroup()
+    {
+        $attributeSetId = 1;
+        $groupData = $this->createGroupData($attributeSetId);
+        $groupData['attribute_group_name'] = 'empty_attribute_group_updated';
+
+        $result = $this->createGroup($attributeSetId, $groupData);
+        $this->assertArrayHasKey('attribute_group_id', $result);
+        $this->assertNotNull($result['attribute_group_id']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/empty_attribute_group.php
+     */
+    public function testDeleteGroup()
+    {
+        $group = $this->getGroupByName('empty_attribute_group');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/groups/" . $group->getId(),
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, ['groupId' => $group->getId()]));
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testCreateGroupWithAttributeSetThatDoesNotExist()
+    {
+        $attributeSetId = -1;
+        $this->createGroup($attributeSetId);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/empty_attribute_group.php
+     */
+    public function testUpdateGroup()
+    {
+        $attributeSetId = 1;
+        $group = $this->getGroupByName('empty_attribute_group');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeSetId . '/groups',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        $newGroupData = $this->createGroupData($attributeSetId);
+        $newGroupData['attribute_group_name'] = 'empty_attribute_group_updated';
+        $newGroupData['attribute_group_id'] = $group->getId();
+
+        $result = $this->_webApiCall($serviceInfo, ['group' => $newGroupData]);
+
+        $this->assertArrayHasKey('attribute_group_id', $result);
+        $this->assertEquals($group->getId(), $result['attribute_group_id']);
+        $this->assertArrayHasKey('attribute_group_name', $result);
+        $this->assertEquals($newGroupData['attribute_group_name'], $result['attribute_group_name']);
+    }
+
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'attribute_set_id',
+                                'value' => 1,
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/groups/list",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['attribute_group_name']);
+        $this->assertNotNull($response['items'][0]['attribute_group_id']);
+    }
+
+    /**
+     * @param $attributeSetId
+     * @return array|bool|float|int|string
+     */
+    protected function createGroup($attributeSetId, $groupData = null)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/groups',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        return $this->_webApiCall(
+            $serviceInfo,
+            ['group' => $groupData ? $groupData : $this->createGroupData($attributeSetId)]
+        );
+    }
+
+    /**
+     * @param $attributeSetId
+     * @return array
+     */
+    protected function createGroupData($attributeSetId)
+    {
+        return [
+            'attribute_group_name' => 'empty_attribute_group',
+            'attribute_set_id' => $attributeSetId
+        ];
+    }
+
+    /**
+     * Retrieve attribute group based on given name.
+     * This utility methods assumes that there is only one attribute group with given name,
+     *
+     * @param string $groupName
+     * @return \Magento\Eav\Model\Entity\Attribute\Group|null
+     */
+    protected function getGroupByName($groupName)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Attribute\Group */
+        $attributeGroup = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Group')
+            ->load($groupName, 'attribute_group_name');
+        if ($attributeGroup->getId() === null) {
+            return null;
+        }
+        return $attributeGroup;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..14f8614829e033dfd41bd61ee6ba9cd815608979
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeManagementTest.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductAttributeManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductAttributeManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/attribute-sets';
+
+    public function testGetAttributes()
+    {
+        $attributeSetId = \Magento\Catalog\Api\Data\ProductAttributeInterface::DEFAULT_ATTRIBUTE_SET_ID;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeSetId . '/attributes',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAttributes',
+            ],
+        ];
+        $attributes = $this->_webApiCall($serviceInfo, ['attributeSetId' => $attributeSetId]);
+
+        $this->assertTrue(count($attributes) > 0);
+        $this->assertArrayHasKey('attribute_code', $attributes[0]);
+        $this->assertArrayHasKey('attribute_id', $attributes[0]);
+        $this->assertArrayHasKey('default_frontend_label', $attributes[0]);
+        $this->assertNotNull($attributes[0]['attribute_code']);
+        $this->assertNotNull($attributes[0]['attribute_id']);
+        $this->assertNotNull($attributes[0]['default_frontend_label']);
+    }
+
+    public function testAssignAttribute()
+    {
+        $this->assertNotNull(
+            $this->_webApiCall(
+                $this->getAssignServiceInfo(),
+                $this->getAttributeData()
+            )
+        );
+    }
+
+    public function testAssignAttributeWrongAttributeSet()
+    {
+        $payload = $this->getAttributeData();
+        $payload['attributeSetId'] = -1;
+
+        $expectedMessage = 'AttributeSet with id "' . $payload['attributeSetId'] . '" does not exist.';
+
+        try {
+            $this->_webApiCall($this->getAssignServiceInfo(), $payload);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    public function testAssignAttributeWrongAttributeGroup()
+    {
+        $payload = $this->getAttributeData();
+        $payload['attributeGroupId'] = -1;
+        $expectedMessage = 'Group with id "' . $payload['attributeGroupId'] . '" does not exist.';
+
+        try {
+            $this->_webApiCall($this->getAssignServiceInfo(), $payload);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    public function testAssignAttributeWrongAttribute()
+    {
+        $payload = $this->getAttributeData();
+        $payload['attributeCode'] = 'badCode';
+        $expectedMessage = 'Attribute with attributeCode "' . $payload['attributeCode'] . '" does not exist.';
+
+        try {
+            $this->_webApiCall($this->getAssignServiceInfo(), $payload);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    public function testUnassignAttribute()
+    {
+        $payload = $this->getAttributeData();
+
+        //Assign attribute to attribute set
+        /** @var \Magento\Eav\Model\AttributeManagement $attributeManagement */
+        $attributeManagement = Bootstrap::getObjectManager()->get('Magento\Eav\Model\AttributeManagement');
+        $attributeManagement->assign(
+            \Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE,
+            $payload['attributeSetId'],
+            $payload['attributeGroupId'],
+            $payload['attributeCode'],
+            $payload['sortOrder']
+        );
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH .
+                    '/' . $payload['attributeSetId'] .
+                    '/attributes/' .
+                    $payload['attributeCode'],
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Unassign',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall(
+                $serviceInfo,
+                [
+                    'attributeSetId' => $payload['attributeSetId'],
+                    'attributeCode' => $payload['attributeCode']
+                ]
+            )
+        );
+    }
+
+    protected function getAttributeData()
+    {
+        return [
+            'attributeSetId' => \Magento\Catalog\Api\Data\ProductAttributeInterface::DEFAULT_ATTRIBUTE_SET_ID,
+            'attributeGroupId' => 8,
+            'attributeCode' => 'cost',
+            'sortOrder' => 3
+        ];
+    }
+
+    protected function getAssignServiceInfo()
+    {
+        return [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/attributes',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Assign',
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb480d3702a2130ac68a57566b7938f3fe0ba482
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php
@@ -0,0 +1,647 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+use Magento\TestFramework\Helper\Bootstrap;
+
+class ProductAttributeMediaGalleryManagementInterfaceTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * Default create service request information (product with SKU 'simple' is used)
+     *
+     * @var array
+     */
+    protected $createServiceInfo;
+
+    /**
+     * Default update service request information (product with SKU 'simple' is used)
+     *
+     * @var array
+     */
+    protected $updateServiceInfo;
+
+    /**
+     * Default delete service request information (product with SKU 'simple' is used)
+     *
+     * @var array
+     */
+    protected $deleteServiceInfo;
+
+    /**
+     * @var string
+     */
+    protected $testImagePath;
+
+    protected function setUp()
+    {
+        $this->createServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/simple/media',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1Create',
+            ],
+        ];
+        $this->updateServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/simple/media',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1Update',
+            ],
+        ];
+        $this->deleteServiceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1Remove',
+            ],
+        ];
+        $this->testImagePath = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'test_image.jpg';
+    }
+
+    /**
+     * Retrieve product that was updated by test
+     *
+     * @return \Magento\Catalog\Model\Product
+     */
+    protected function getTargetSimpleProduct()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        return $objectManager->get('Magento\Catalog\Model\ProductFactory')->create()->load(1);
+    }
+
+    /**
+     * Retrieve target product image ID
+     *
+     * Target product must have single image if this function is used
+     *
+     * @return int
+     */
+    protected function getTargetGalleryEntryId()
+    {
+        $mediaGallery = $this->getTargetSimpleProduct()->getData('media_gallery');
+        return (int)$mediaGallery['images'][0]['value_id'];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testCreate()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'entryContent' => [
+                'entry_data' => base64_encode(file_get_contents($this->testImagePath)),
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+            // Store ID is not provided so the default one must be used
+        ];
+
+        $actualResult = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $targetProduct = $this->getTargetSimpleProduct();
+        $mediaGallery = $targetProduct->getData('media_gallery');
+
+        $this->assertCount(1, $mediaGallery['images']);
+        $updatedImage = $mediaGallery['images'][0];
+        $this->assertEquals($actualResult, $updatedImage['value_id']);
+        $this->assertEquals('Image Text', $updatedImage['label']);
+        $this->assertEquals(1, $updatedImage['position']);
+        $this->assertEquals(0, $updatedImage['disabled']);
+        $this->assertEquals('Image Text', $updatedImage['label_default']);
+        $this->assertEquals(1, $updatedImage['position_default']);
+        $this->assertEquals(0, $updatedImage['disabled_default']);
+        $this->assertStringStartsWith('/t/e/test_image', $updatedImage['file']);
+        $this->assertEquals($updatedImage['file'], $targetProduct->getData('image'));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testCreateWithNotDefaultStoreId()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'entryContent' => [
+                'entry_data' => base64_encode(file_get_contents($this->testImagePath)),
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+            'storeId' => 1,
+        ];
+
+        $actualResult = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $targetProduct = $this->getTargetSimpleProduct();
+        $mediaGallery = $targetProduct->getData('media_gallery');
+        $this->assertCount(1, $mediaGallery['images']);
+        $updatedImage = $mediaGallery['images'][0];
+        // Values for not default store view were provided
+        $this->assertEquals('Image Text', $updatedImage['label']);
+        $this->assertEquals($actualResult, $updatedImage['value_id']);
+        $this->assertEquals(1, $updatedImage['position']);
+        $this->assertEquals(0, $updatedImage['disabled']);
+        $this->assertStringStartsWith('/t/e/test_image', $updatedImage['file']);
+        $this->assertEquals($updatedImage['file'], $targetProduct->getData('image'));
+        // No values for default store view were provided
+        $this->assertNull($updatedImage['label_default']);
+        $this->assertNull($updatedImage['position_default']);
+        $this->assertNull($updatedImage['disabled_default']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     */
+    public function testUpdate()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => $this->getTargetGalleryEntryId(),
+                'label' => 'Updated Image Text',
+                'position' => 10,
+                'types' => ['thumbnail'],
+                'is_disabled' => true,
+            ],
+            // Store ID is not provided so the default one must be used
+        ];
+
+        $this->updateServiceInfo['rest']['resourcePath'] = $this->updateServiceInfo['rest']['resourcePath']
+            . '/' . $this->getTargetGalleryEntryId();
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+
+        $targetProduct = $this->getTargetSimpleProduct();
+        $this->assertEquals('/m/a/magento_image.jpg', $targetProduct->getData('thumbnail'));
+        $this->assertNull($targetProduct->getData('image'));
+        $this->assertNull($targetProduct->getData('small_image'));
+        $mediaGallery = $targetProduct->getData('media_gallery');
+        $this->assertCount(1, $mediaGallery['images']);
+        $updatedImage = $mediaGallery['images'][0];
+        $this->assertEquals('Updated Image Text', $updatedImage['label']);
+        $this->assertEquals('/m/a/magento_image.jpg', $updatedImage['file']);
+        $this->assertEquals(10, $updatedImage['position']);
+        $this->assertEquals(1, $updatedImage['disabled']);
+        $this->assertEquals('Updated Image Text', $updatedImage['label_default']);
+        $this->assertEquals(10, $updatedImage['position_default']);
+        $this->assertEquals(1, $updatedImage['disabled_default']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     */
+    public function testUpdateWithNotDefaultStoreId()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => $this->getTargetGalleryEntryId(),
+                'label' => 'Updated Image Text',
+                'position' => 10,
+                'types' => ['thumbnail'],
+                'is_disabled' => true,
+            ],
+            'storeId' => 1,
+        ];
+
+        $this->updateServiceInfo['rest']['resourcePath'] = $this->updateServiceInfo['rest']['resourcePath']
+            . '/' . $this->getTargetGalleryEntryId();
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+
+        $targetProduct = $this->getTargetSimpleProduct();
+        $this->assertEquals('/m/a/magento_image.jpg', $targetProduct->getData('thumbnail'));
+        $this->assertNull($targetProduct->getData('image'));
+        $this->assertNull($targetProduct->getData('small_image'));
+        $mediaGallery = $targetProduct->getData('media_gallery');
+        $this->assertCount(1, $mediaGallery['images']);
+        $updatedImage = $mediaGallery['images'][0];
+        // Not default store view values were updated
+        $this->assertEquals('Updated Image Text', $updatedImage['label']);
+        $this->assertEquals('/m/a/magento_image.jpg', $updatedImage['file']);
+        $this->assertEquals(10, $updatedImage['position']);
+        $this->assertEquals(1, $updatedImage['disabled']);
+        // Default store view values were not updated
+        $this->assertEquals('Image Alt Text', $updatedImage['label_default']);
+        $this->assertEquals(1, $updatedImage['position_default']);
+        $this->assertEquals(0, $updatedImage['disabled_default']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     */
+    public function testDelete()
+    {
+        $entryId = $this->getTargetGalleryEntryId();
+        $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/simple/media/{$entryId}";
+        $requestData = [
+            'productSku' => 'simple',
+            'entryId' => $this->getTargetGalleryEntryId(),
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->deleteServiceInfo, $requestData));
+        $targetProduct = $this->getTargetSimpleProduct();
+        $mediaGallery = $targetProduct->getData('media_gallery');
+        $this->assertCount(0, $mediaGallery['images']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no store with provided ID.
+     */
+    public function testCreateThrowsExceptionIfThereIsNoStoreWithProvidedStoreId()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'storeId' => 9999, // target store view does not exist
+            'entryContent' => [
+                'entry_data' => base64_encode(file_get_contents($this->testImagePath)),
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage The image content must be valid base64 encoded data.
+     */
+    public function testCreateThrowsExceptionIfProvidedContentIsNotBase64Encoded()
+    {
+        $encodedContent = 'not_a_base64_encoded_content';
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'is_disabled' => false,
+                'types' => ['image'],
+            ],
+            'entryContent' => [
+                'entry_data' => $encodedContent,
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage The image content must be valid base64 encoded data.
+     */
+    public function testCreateThrowsExceptionIfProvidedContentIsNotAnImage()
+    {
+        $encodedContent = base64_encode('not_an_image');
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'is_disabled' => false,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+            ],
+            'entryContent' => [
+                'entry_data' => $encodedContent,
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage The image MIME type is not valid or not supported.
+     */
+    public function testCreateThrowsExceptionIfProvidedImageHasWrongMimeType()
+    {
+        $encodedContent = base64_encode(file_get_contents($this->testImagePath));
+        $requestData = [
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'productSku' => 'simple',
+            'entryContent' => [
+                'entry_data' => $encodedContent,
+                'mime_type' => 'wrong_mime_type',
+                'name' => 'test_image',
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testCreateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->createServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media';
+        $requestData = [
+            'productSku' => 'wrong_product_sku',
+            'entry' => [
+                'id' => null,
+                'position' => 1,
+                'label' => 'Image Text',
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'entryContent' => [
+                'entry_data' => base64_encode(file_get_contents($this->testImagePath)),
+                'mime_type' => 'image/jpeg',
+                'name' => 'test_image',
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided image name contains forbidden characters.
+     */
+    public function testCreateThrowsExceptionIfProvidedImageNameContainsForbiddenCharacters()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => null,
+                'label' => 'Image Text',
+                'position' => 1,
+                'types' => ['image'],
+                'is_disabled' => false,
+            ],
+            'entryContent' => [
+                'entry_data' => base64_encode(file_get_contents($this->testImagePath)),
+                'mime_type' => 'image/jpeg',
+                'name' => 'test/\\{}|:"<>', // Cannot contain \ / : * ? " < > |
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no store with provided ID.
+     */
+    public function testUpdateIfThereIsNoStoreWithProvidedStoreId()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => $this->getTargetGalleryEntryId(),
+                'label' => 'Updated Image Text',
+                'position' => 10,
+                'types' => ['thumbnail'],
+                'is_disabled' => true,
+            ],
+            'storeId' => 9999, // target store view does not exist
+        ];
+
+        $this->updateServiceInfo['rest']['resourcePath'] = $this->updateServiceInfo['rest']['resourcePath']
+            . '/' . $this->getTargetGalleryEntryId();
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testUpdateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media'
+            . '/' . $this->getTargetGalleryEntryId();
+        $requestData = [
+            'productSku' => 'wrong_product_sku',
+            'entry' => [
+                'id' => 9999,
+                'label' => 'Updated Image Text',
+                'position' => 1,
+                'types' => ['thumbnail'],
+                'is_disabled' => true,
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no image with provided ID.
+     */
+    public function testUpdateThrowsExceptionIfThereIsNoImageWithGivenId()
+    {
+        $requestData = [
+            'productSku' => 'simple',
+            'entry' => [
+                'id' => 9999,
+                'label' => 'Updated Image Text',
+                'position' => 1,
+                'types' => ['thumbnail'],
+                'is_disabled' => true,
+            ],
+            'storeId' => 0,
+        ];
+
+        $this->updateServiceInfo['rest']['resourcePath'] = $this->updateServiceInfo['rest']['resourcePath']
+            . '/' . $this->getTargetGalleryEntryId();
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testDeleteThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->deleteServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media/9999';
+        $requestData = [
+            'productSku' => 'wrong_product_sku',
+            'entryId' => 9999,
+        ];
+
+        $this->_webApiCall($this->deleteServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no image with provided ID.
+     */
+    public function testDeleteThrowsExceptionIfThereIsNoImageWithGivenId()
+    {
+        $this->deleteServiceInfo['rest']['resourcePath'] = '/V1/products/simple/media/9999';
+        $requestData = [
+            'productSku' => 'simple',
+            'entryId' => 9999,
+        ];
+
+        $this->_webApiCall($this->deleteServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     */
+    public function testGet()
+    {
+        $productSku = 'simple';
+
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Model\ProductRepository $repository */
+        $repository = $objectManager->create('Magento\Catalog\Model\ProductRepository');
+        $product = $repository->get($productSku);
+        $image = current($product->getMediaGallery('images'));
+        $imageId = $image['value_id'];
+
+        $expected = [
+            'label' => $image['label'],
+            'position' => $image['position'],
+            'is_disabled' => (bool)$image['disabled'],
+            'file' => $image['file'],
+            'types' => ['image', 'small_image', 'thumbnail'],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku . '/media/' . $imageId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1Get',
+            ],
+        ];
+        $requestData = [
+            'productSku' => $productSku,
+            'imageId' => $imageId,
+        ];
+        $data = $this->_webApiCall($serviceInfo, $requestData);
+        $actual = (array) $data;
+        $this->assertEquals($expected['label'], $actual['label']);
+        $this->assertEquals($expected['position'], $actual['position']);
+        $this->assertEquals($expected['file'], $actual['file']);
+        $this->assertEquals($expected['types'], $actual['types']);
+        $this->assertEquals($expected['is_disabled'], (bool)$actual['is_disabled']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
+     */
+    public function testGetList()
+    {
+        $productSku = 'simple'; //from fixture
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . urlencode($productSku) . '/media',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1GetList',
+            ],
+        ];
+
+        $requestData = [
+            'productSku' => $productSku,
+        ];
+        $imageList = $this->_webApiCall($serviceInfo, $requestData);
+
+        $image = reset($imageList);
+        $this->assertEquals('/m/a/magento_image.jpg', $image['file']);
+        $this->assertNotEmpty($image['types']);
+        $imageTypes = $image['types'];
+        $this->assertContains('image', $imageTypes);
+        $this->assertContains('small_image', $imageTypes);
+        $this->assertContains('thumbnail', $imageTypes);
+    }
+
+    public function testGetListForAbsentSku()
+    {
+        $productSku = 'absent_sku_' . time();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . urlencode($productSku) . '/media',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogProductAttributeMediaGalleryManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductAttributeMediaGalleryManagementV1GetList',
+            ],
+        ];
+
+        $requestData = [
+            'productSku' => $productSku,
+        ];
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->setExpectedException('SoapFault', 'Requested product doesn\'t exist');
+        } else {
+            $this->setExpectedException('Exception', '', 404);
+        }
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b687f2a6f4fe15216c03ebd355a75feb756243f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Eav\Api\Data\AttributeOptionInterface;
+use Magento\Eav\Api\Data\AttributeOptionLabelInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductAttributeOptionManagementInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductAttributeOptionManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/attributes';
+
+    public function testGetItems()
+    {
+        $testAttributeCode = 'quantity_and_stock_status';
+        $expectedOptions = [
+            [
+                AttributeOptionInterface::VALUE => '1',
+                AttributeOptionInterface::LABEL => 'In Stock',
+            ],
+            [
+                AttributeOptionInterface::VALUE => '0',
+                AttributeOptionInterface::LABEL => 'Out of Stock',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getItems',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, ['attributeCode' => $testAttributeCode]);
+
+        $this->assertTrue(is_array($response));
+        $this->assertEquals($expectedOptions, $response);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/Model/Product/Attribute/_files/select_attribute.php
+     */
+    public function testAdd()
+    {
+        $testAttributeCode = 'select_attribute';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'add',
+            ],
+        ];
+
+        $optionData = [
+            AttributeOptionInterface::LABEL => 'new color',
+            AttributeOptionInterface::VALUE => 'grey',
+            AttributeOptionInterface::SORT_ORDER => 100,
+            AttributeOptionInterface::IS_DEFAULT => true,
+            AttributeOptionInterface::STORE_LABELS => [
+                [
+                    AttributeOptionLabelInterface::LABEL => 'DE label',
+                    AttributeOptionLabelInterface::STORE_ID => 1,
+                ],
+            ],
+        ];
+
+        $response = $this->_webApiCall(
+            $serviceInfo,
+            [
+                'attributeCode' => $testAttributeCode,
+                'option' => $optionData,
+            ]
+        );
+
+        $this->assertTrue($response);
+        $updatedData = $this->getAttributeOptions($testAttributeCode);
+        $lastOption = array_pop($updatedData);
+        $this->assertEquals(
+            $optionData[AttributeOptionInterface::STORE_LABELS][0][AttributeOptionLabelInterface::LABEL],
+            $lastOption['label']
+        );
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/Model/Product/Attribute/_files/select_attribute.php
+     */
+    public function testDelete()
+    {
+        $attributeCode = 'select_attribute';
+        //get option Id
+        $optionList = $this->getAttributeOptions($attributeCode);
+        $this->assertGreaterThan(0, count($optionList));
+        $lastOption = array_pop($optionList);
+        $this->assertNotEmpty($lastOption['value']);
+        $optionId = $lastOption['value'];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeCode . '/options/' . $optionId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'delete',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall(
+            $serviceInfo,
+            [
+                'attributeCode' => $attributeCode,
+                'optionId' => $optionId,
+            ]
+        ));
+        $updatedOptions = $this->getAttributeOptions($attributeCode);
+        $this->assertEquals($optionList, $updatedOptions);
+    }
+
+    /**
+     * @param $testAttributeCode
+     * @return array|bool|float|int|string
+     */
+    private function getAttributeOptions($testAttributeCode)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $testAttributeCode . '/options',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getItems',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['attributeCode' => $testAttributeCode]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..20742ba9ee0e64cc8972160e1c4fb4c109355f0a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeRepositoryTest.php
@@ -0,0 +1,266 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductAttributeRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductAttributeRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/attributes';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_attribute.php
+     */
+    public function testGet()
+    {
+        $attributeCode = 'test_attribute_code_333';
+        $attribute = $this->getAttribute($attributeCode);
+
+        $this->assertTrue(is_array($attribute));
+        $this->assertArrayHasKey('attribute_id', $attribute);
+        $this->assertArrayHasKey('attribute_code', $attribute);
+        $this->assertEquals($attributeCode, $attribute['attribute_code']);
+    }
+
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'frontend_input',
+                                'value' => 'textarea',
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+            'entityTypeCode' => \Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE,
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['default_frontend_label']);
+        $this->assertNotNull($response['items'][0]['attribute_id']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/Model/Product/Attribute/_files/create_attribute_service.php
+     */
+    public function testCreate()
+    {
+        $attributeCode = 'label_attr_code3df4tr3';
+        $attribute = $this->createAttribute($attributeCode);
+        $this->assertArrayHasKey('attribute_id', $attribute);
+        $this->assertEquals($attributeCode, $attribute['attribute_code']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_attribute.php
+     */
+    public function testCreateWithExceptionIfAttributeAlreadyExists()
+    {
+        $attributeCode = 'test_attribute_code_333';
+        try {
+            $this->createAttribute($attributeCode);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            //Expects soap exception
+        } catch (\Exception $e) {
+            $this->assertEquals(HTTPExceptionCodes::HTTP_INTERNAL_ERROR, $e->getCode());
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_attribute.php
+     */
+    public function testUpdate()
+    {
+        $attributeCode = 'test_attribute_code_333';
+        $attribute = $this->getAttribute($attributeCode);
+
+        $attributeData = [
+            'attribute' => [
+                'attribute_code' => $attributeCode,
+                'frontend_labels' => [
+                    ['store_id' => 0, 'label' => 'front_lbl_new'],
+                ],
+                'default_value' => 'default value new',
+                'is_required' => false,
+                'frontend_input' => 'text',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attribute['attribute_id'],
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $attributeData['attribute']['attributeId'] = $attribute['attribute_id'];
+        }
+        $result = $this->_webApiCall($serviceInfo, $attributeData);
+
+        $this->assertEquals($attribute['attribute_id'], $result['attribute_id']);
+        $this->assertEquals($attributeCode, $result['attribute_code']);
+        $this->assertEquals('default value new', $result['default_value']);
+        $this->assertEquals('front_lbl_new', $result['default_frontend_label']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_attribute.php
+     */
+    public function testDeleteById()
+    {
+        $attributeCode = 'test_attribute_code_333';
+        $this->assertTrue($this->deleteAttribute($attributeCode));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_attribute.php
+     */
+    public function testDeleteNoSuchEntityException()
+    {
+        $attributeCode = 'some_test_code';
+        $expectedMessage = 'Attribute with attributeCode "' . $attributeCode . '" does not exist.';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeCode,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'deleteById',
+            ],
+        ];
+
+        try {
+            $this->_webApiCall($serviceInfo, ['attributeCode' => $attributeCode]);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    /**
+     * @param $attributeCode
+     * @return array|bool|float|int|string
+     */
+    protected function createAttribute($attributeCode)
+    {
+        $attributeData = [
+            'attribute' => [
+                'attribute_code' => $attributeCode,
+                'frontend_labels' => [
+                    ['store_id' => 0, 'label' => 'front_lbl'],
+                ],
+                'default_value' => 'default value',
+                'frontend_input' => 'textarea',
+                'is_required' => true,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, $attributeData);
+    }
+
+    /**
+     * @param $attributeCode
+     * @return array|bool|float|int|string
+     */
+    protected function getAttribute($attributeCode)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeCode,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        return $this->_webApiCall($serviceInfo, ['attributeCode' => $attributeCode]);
+    }
+
+    /**
+     * Delete attribute by code
+     *
+     * @param $attributeCode
+     * @return array|bool|float|int|string
+     */
+    protected function deleteAttribute($attributeCode)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $attributeCode,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'deleteById',
+            ],
+        ];
+        return $this->_webApiCall($serviceInfo, ['attributeCode' => $attributeCode]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeTypesListTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeTypesListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5967b8503bfcd635db17e0725b60dcef321e33f4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeTypesListTest.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductAttributeTypesListTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductAttributeTypesListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/attributes';
+
+    public function testGetItems()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/types',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetItems',
+            ],
+        ];
+        $types = $this->_webApiCall($serviceInfo);
+
+        $this->assertTrue(count($types) > 0);
+        $this->assertArrayHasKey('value', $types[0]);
+        $this->assertArrayHasKey('label', $types[0]);
+        $this->assertNotNull($types[0]['value']);
+        $this->assertNotNull($types[0]['label']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1995c194bd5b81d0fa45d0c3027c04628e228854
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
@@ -0,0 +1,367 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+class ProductCustomOptionRepositoryTest extends WebapiAbstract
+{
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    const SERVICE_NAME = 'catalogProductCustomOptionRepositoryV1';
+
+    /**
+     * @var \Magento\Catalog\Model\ProductFactory
+     */
+    protected $productFactory;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->productFactory = $this->objectManager->get('Magento\Catalog\Model\ProductFactory');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_options.php
+     * @magentoAppIsolation enabled
+     */
+    public function testRemove()
+    {
+        $sku = 'simple';
+        /** @var  \Magento\Catalog\Model\Product $product */
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $product->load(1);
+        $customOptions = $product->getOptions();
+        $optionId = array_pop($customOptions)->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/products/$sku/options/$optionId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'DeleteByIdentifier',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, ['productSku' => $sku, 'optionId' => $optionId]));
+        /** @var  \Magento\Catalog\Model\Product $product */
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $product->load(1);
+        $this->assertNull($product->getOptionById($optionId));
+        $this->assertEquals(9, count($product->getOptions()));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_options.php
+     * @magentoAppIsolation enabled
+     */
+    public function testGet()
+    {
+        $productSku = 'simple';
+        /** @var \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface $service */
+        $service = Bootstrap::getObjectManager()
+            ->get('Magento\Catalog\Api\ProductCustomOptionRepositoryInterface');
+        $options = $service->getList('simple');
+        $option = current($options);
+        $optionId = $option->getOptionId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku . "/options/" . $optionId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        $option = $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'optionId' => $optionId]);
+        unset($option['product_sku']);
+        unset($option['option_id']);
+        $excepted = include '_files/product_options.php';
+        $this->assertEquals($excepted[0], $option);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_options.php
+     * @magentoAppIsolation enabled
+     */
+    public function testGetList()
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku . "/options",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $options = $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+
+        /** Unset dynamic data */
+        foreach ($options as $key => $value) {
+            unset($options[$key]['product_sku']);
+            unset($options[$key]['option_id']);
+            if (!empty($options[$key]['values'])) {
+                foreach ($options[$key]['values'] as $newKey => $valueData) {
+                    unset($options[$key]['values'][$newKey]['option_type_id']);
+                }
+            }
+        }
+
+        $excepted = include '_files/product_options.php';
+        $this->assertEquals(count($excepted), count($options));
+
+        //in order to make assertion result readable we need to check each element separately
+        foreach ($excepted as $index => $value) {
+            $this->assertEquals($value, $options[$index]);
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_without_options.php
+     * @magentoAppIsolation enabled
+     * @dataProvider optionDataProvider
+     */
+    public function testSave($optionData)
+    {
+        $productSku = 'simple';
+
+        $optionDataPost = $optionData;
+        $optionDataPost['product_sku'] = $productSku;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/options',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, ['option' => $optionDataPost]);
+        unset($result['product_sku']);
+        unset($result['option_id']);
+        if (!empty($result['values'])) {
+            foreach ($result['values'] as $key => $value) {
+                unset($result['values'][$key]['option_type_id']);
+            }
+        }
+        $this->assertEquals($optionData, $result);
+    }
+
+    public function optionDataProvider()
+    {
+        $fixtureOptions = [];
+        $fixture = include '_files/product_options.php';
+        foreach ($fixture as $item) {
+            $fixtureOptions[$item['type']] = [
+                'optionData' => $item,
+            ];
+        };
+
+        return $fixtureOptions;
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_without_options.php
+     * @magentoAppIsolation enabled
+     * @dataProvider optionNegativeDataProvider
+     */
+    public function testAddNegative($optionData)
+    {
+        $productSku = 'simple';
+        $optionDataPost = $optionData;
+        $optionDataPost['product_sku'] = $productSku;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/products/options",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->setExpectedException('SoapFault', 'Could not save product option');
+        } else {
+            $this->setExpectedException('Exception', '', 400);
+        }
+        $this->_webApiCall($serviceInfo, ['option' => $optionDataPost]);
+    }
+
+    public function optionNegativeDataProvider()
+    {
+        $fixtureOptions = [];
+        $fixture = include '_files/product_options_negative.php';
+        foreach ($fixture as $key => $item) {
+            $fixtureOptions[$key] = [
+                'optionData' => $item,
+            ];
+        };
+
+        return $fixtureOptions;
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_options.php
+     * @magentoAppIsolation enabled
+     */
+    public function testUpdate()
+    {
+        $productSku = 'simple';
+        /** @var \Magento\Catalog\Model\ProductRepository $optionReadService */
+        $productRepository = $this->objectManager->create(
+            'Magento\Catalog\Model\ProductRepository'
+        );
+
+        $options = $productRepository->get($productSku, true)->getOptions();
+        $option = array_shift($options);
+        $optionId = $option->getOptionId();
+        $optionDataPost = [
+            'product_sku' => $productSku,
+            'title' => $option->getTitle() . "_updated",
+            'type' => $option->getType(),
+            'sort_order' => $option->getSortOrder(),
+            'is_require' => $option->getIsRequire(),
+            'price' => $option->getPrice(),
+            'price_type' => $option->getPriceType(),
+            'sku' => $option->getSku(),
+            'max_characters' => 500,
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/options/' . $optionId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $optionDataPost['option_id'] = $optionId;
+            $updatedOption = $this->_webApiCall(
+                $serviceInfo, [ 'id' => $optionId, 'option' => $optionDataPost]
+            );
+        } else {
+            $updatedOption = $this->_webApiCall(
+                $serviceInfo, ['option' => $optionDataPost]
+            );
+        }
+
+        unset($updatedOption['values']);
+        $optionDataPost['option_id'] = $option->getOptionId();
+        $this->assertEquals($optionDataPost, $updatedOption);
+    }
+
+    /**
+     * @param string $optionType
+     *
+     * @magentoApiDataFixture Magento/Catalog/_files/product_with_options.php
+     * @magentoAppIsolation enabled
+     * @dataProvider validOptionDataProvider
+     */
+    public function testUpdateOptionAddingNewValue($optionType)
+    {
+        $productId = 1;
+        $fixtureOption = null;
+        $valueData = [
+            'price' => 100500,
+            'price_type' => 'fixed',
+            'sku' => 'new option sku ' . $optionType,
+            'title' => 'New Option Title',
+            'sort_order' => 100,
+        ];
+
+        $product = $this->productFactory->create();
+        $product->load($productId);
+
+        /**@var $option \Magento\Catalog\Model\Product\Option */
+        foreach ($product->getOptions() as $option) {
+            if ($option->getType() == $optionType) {
+                $fixtureOption = $option;
+                break;
+            }
+        }
+
+        $values = [];
+        foreach ($option->getValues() as $key => $value) {
+            $values[] = [
+                'price' => $value->getPrice(),
+                'price_type' => $value->getPriceType(),
+                'sku' => $value->getSku(),
+                'title' => $value->getTitle(),
+                'sort_order' => $value->getSortOrder(),
+        ];
+        }
+        $values[] = $valueData;
+        $data = [
+            'product_sku' => $option->getProductSku(),
+            'title' => $option->getTitle(),
+            'type' => $option->getType(),
+            'is_require' => $option->getIsRequire(),
+            'sort_order' => $option->getSortOrder(),
+            'values' => $values,
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/options/' . $fixtureOption->getId(),
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $data['option_id'] = $fixtureOption->getId();
+            $valueObject = $this->_webApiCall(
+                $serviceInfo, [ 'option_id' => $fixtureOption->getId(), 'option' => $data]
+            );
+        } else {
+            $valueObject = $this->_webApiCall(
+                $serviceInfo, ['option' => $data]
+            );
+        }
+
+        $values = end($valueObject['values']);
+        $this->assertEquals($valueData['price'], $values['price']);
+        $this->assertEquals($valueData['price_type'], $values['price_type']);
+        $this->assertEquals($valueData['sku'], $values['sku']);
+        $this->assertEquals('New Option Title', $values['title']);
+        $this->assertEquals(100, $values['sort_order']);
+    }
+
+    public function validOptionDataProvider()
+    {
+        return [
+            'drop_down' => ['drop_down'],
+            'checkbox' => ['checkbox'],
+            'radio' => ['radio'],
+            'multiple' => ['multiple']
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionTypeListTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionTypeListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb0f890231e58871102aa684a33ccb699d8902b1
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionTypeListTest.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+class ProductCustomOptionTypeListTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/products/options/';
+
+    const SERVICE_NAME = 'catalogProductCustomOptionTypeListV1';
+
+    /**
+     * @magentoAppIsolation enabled
+     */
+    public function testGetTypes()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "types",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => 'V1',
+                'operation' => self::SERVICE_NAME . 'GetItems',
+            ],
+        ];
+        $types = $this->_webApiCall($serviceInfo);
+        $excepted = [
+            'label' => __('Drop-down'),
+            'code' => 'drop_down',
+            'group' => __('Select'),
+        ];
+        $this->assertGreaterThanOrEqual(10, count($types));
+        $this->assertContains($excepted, $types);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductGroupPriceManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductGroupPriceManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..035931302519d5baa2b598bb2865008828b1e045
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductGroupPriceManagementTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductGroupPriceManagementTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductGroupPriceManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_group_prices.php
+     */
+    public function testGetList()
+    {
+        $productSku = 'simple_with_group_price';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/group-prices',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $groupPriceList = $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+        $this->assertCount(2, $groupPriceList);
+        $this->assertEquals(9, $groupPriceList[0]['value']);
+        $this->assertEquals(7, $groupPriceList[1]['value']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_group_prices.php
+     */
+    public function testDelete()
+    {
+        $productSku = 'simple_with_group_price';
+        $customerGroupId = \Magento\Customer\Model\GroupManagement::NOT_LOGGED_IN_ID;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . "/group-prices/" . $customerGroupId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Remove',
+            ],
+        ];
+        $requestData = ['productSku' => $productSku, 'customerGroupId' => $customerGroupId];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testAdd()
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku . '/group-prices/1/price/10',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Add',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'customerGroupId' => 1, 'price' => 10]);
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Api\ProductGroupPriceManagementInterface $service */
+        $service = $objectManager->get('Magento\Catalog\Api\ProductGroupPriceManagementInterface');
+        $prices = $service->getList($productSku);
+        $this->assertCount(1, $prices);
+        $this->assertEquals(10, $prices[0]->getValue());
+        $this->assertEquals(1, $prices[0]->getCustomerGroupId());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoApiDataFixture Magento/Store/_files/website.php
+     */
+    public function testAddForDifferentWebsite()
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku . '/group-prices/1/price/10',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Add',
+            ],
+
+        ];
+        $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'customerGroupId' => 1, 'price' => 10]);
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Api\ProductGroupPriceManagementInterface $service */
+        $service = $objectManager->get('Magento\Catalog\Api\ProductGroupPriceManagementInterface');
+        $prices = $service->getList($productSku);
+        $this->assertCount(1, $prices);
+        $this->assertEquals(10, $prices[0]->getValue());
+        $this->assertEquals(1, $prices[0]->getCustomerGroupId());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..67df2361c2c7ae928c9ba2f80e83f2d17abec267
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductLinkManagementInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_crosssell.php
+     */
+    public function testGetLinkedProductsCrossSell()
+    {
+        $productSku = 'simple_with_cross';
+        $linkType = 'crosssell';
+
+        $this->assertLinkedProducts($productSku, $linkType);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_related.php
+     */
+    public function testGetLinkedProductsRelated()
+    {
+        $productSku = 'simple_with_cross';
+        $linkType = 'related';
+
+        $this->assertLinkedProducts($productSku, $linkType);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_upsell.php
+     */
+    public function testGetLinkedProductsUpSell()
+    {
+        $productSku = 'simple_with_upsell';
+        $linkType = 'upsell';
+
+        $this->assertLinkedProducts($productSku, $linkType);
+    }
+
+    /**
+     * @param string $productSku
+     * @param int $linkType
+     */
+    protected function assertLinkedProducts($productSku, $linkType)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetLinkedItemsByType',
+            ],
+        ];
+
+        $actual = $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'type' => $linkType]);
+
+        $this->assertEquals('simple', $actual[0]['linked_product_type']);
+        $this->assertEquals('simple', $actual[0]['linked_product_sku']);
+        $this->assertEquals(1, $actual[0]['position']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoApiDataFixture Magento/Catalog/_files/product_virtual.php
+     */
+    public function testAssign()
+    {
+        $linkType = 'related';
+        $productSku = 'simple';
+        $linkData = [
+            'linked_product_type' => 'virtual',
+            'linked_product_sku' => 'virtual-product',
+            'position' => 100,
+            'product_sku' => 'simple',
+            'link_type' => 'related',
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetProductLinks',
+            ],
+        ];
+
+        $arguments = [
+            'productSku' => $productSku,
+            'items' => [$linkData],
+            'type' => $linkType,
+        ];
+
+        $this->_webApiCall($serviceInfo, $arguments);
+        $actual = $this->getLinkedProducts($productSku, 'related');
+        array_walk($actual, function (&$item) {
+            $item = $item->__toArray();
+        });
+        $this->assertEquals([$linkData], $actual);
+    }
+
+    /**
+     * Get list of linked products
+     *
+     * @param string $sku
+     * @param string $linkType
+     * @return \Magento\Catalog\Api\Data\ProductLinkInterface[]
+     */
+    protected function getLinkedProducts($sku, $linkType)
+    {
+        /** @var \Magento\Catalog\Model\ProductLink\Management $linkManagement */
+        $linkManagement = $this->objectManager->get('Magento\Catalog\Api\ProductLinkManagementInterface');
+        $linkedProducts = $linkManagement->getLinkedItemsByType($sku, $linkType);
+
+        return $linkedProducts;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff04d9044a11382fb656ef82e2d8f3a476f147ff
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductLinkRepositoryInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_related_multiple.php
+     * @magentoAppIsolation enabled
+     */
+    public function testDelete()
+    {
+        $productSku = 'simple_with_cross';
+        $linkedSku = 'simple';
+        $linkType = 'related';
+        $this->_webApiCall(
+            [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType . '/' . $linkedSku,
+                    'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+                ],
+                'soap' => [
+                    'service' => self::SERVICE_NAME,
+                    'serviceVersion' => self::SERVICE_VERSION,
+                    'operation' => self::SERVICE_NAME . 'DeleteById',
+                ],
+            ],
+            [
+                'productSku' => $productSku,
+                'type' => $linkType,
+                'linkedProductSku' => $linkedSku
+            ]
+        );
+        /** @var \Magento\Catalog\Model\ProductLink\Management $linkManagement */
+        $linkManagement = $this->objectManager->create('Magento\Catalog\Api\ProductLinkManagementInterface');
+        $linkedProducts = $linkManagement->getLinkedItemsByType($productSku, $linkType);
+        $this->assertCount(1, $linkedProducts);
+        /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $product */
+        $product = current($linkedProducts);
+        $this->assertEquals($product->getLinkedProductSku(), 'simple_with_cross_two');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_related.php
+     */
+    public function testSave()
+    {
+        $productSku = 'simple_with_cross';
+        $linkType = 'related';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        $this->_webApiCall(
+            $serviceInfo,
+            [
+                'entity' => [
+                    'product_sku' => 'simple_with_cross',
+                    'link_type' => 'related',
+                    'linked_product_sku' => 'simple',
+                    'linked_product_type' => 'simple',
+                    'position' => 1000,
+                ]
+            ]
+        );
+
+        /** @var \Magento\Catalog\Model\ProductLink\Management $linkManagement */
+        $linkManagement = $this->objectManager->get('Magento\Catalog\Api\ProductLinkManagementInterface');
+        $actual = $linkManagement->getLinkedItemsByType($productSku, $linkType);
+        $this->assertCount(1, $actual, 'Invalid actual linked products count');
+        $this->assertEquals(1000, $actual[0]->getPosition(), 'Product position is not updated');
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkTypeListTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkTypeListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fb46da2b49e8c635499136c87d24a159b4557f0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkTypeListTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Catalog\Model\Product\Link;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductLinkTypeListTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkTypeListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    public function testGetItems()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . 'links/types',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetItems',
+            ],
+        ];
+        $actual = $this->_webApiCall($serviceInfo);
+        $expectedItems = ['name' => 'related', 'code' => Link::LINK_TYPE_RELATED];
+        $this->assertContains($expectedItems, $actual);
+    }
+
+    public function testGetItemAttributes()
+    {
+        $linkType = 'related';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . 'links/' . $linkType . '/attributes',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetItemAttributes',
+            ],
+        ];
+        $actual = $this->_webApiCall($serviceInfo, ['type' => $linkType]);
+        $expected = [['code' => 'position', 'type' => 'int']];
+        $this->assertEquals($expected, $actual);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductMediaAttributeManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductMediaAttributeManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8939bf5c362a322708c760a29f64d055e686c8f0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductMediaAttributeManagementTest.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductMediaAttributeManagementTest extends WebapiAbstract
+{
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/attribute_set_with_image_attribute.php
+     */
+    public function testGetList()
+    {
+        $attributeSetName = 'attribute_set_with_media_attribute';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/media/types/' . $attributeSetName,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogProductMediaAttributeManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'catalogProductMediaAttributeManagementV1GetList',
+            ],
+        ];
+
+        $requestData = [
+            'attributeSetName' => $attributeSetName,
+        ];
+
+        $mediaAttributes = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertNotEmpty($mediaAttributes);
+        $attribute = $this->getAttributeByCode($mediaAttributes,  'funny_image');
+        $this->assertNotNull($attribute);
+        $this->assertEquals('Funny image', $attribute['default_frontend_label']);
+        $this->assertEquals(1, $attribute['is_user_defined']);
+    }
+
+    /**
+     * Retrieve attribute based on given attribute code
+     *
+     * @param array $attributeList
+     * @param string $attributeCode
+     * @return array|null
+     */
+    protected function getAttributeByCode($attributeList, $attributeCode)
+    {
+        foreach ($attributeList as $attribute) {
+            if ($attributeCode == $attribute['attribute_code']) {
+                return $attribute;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b9e84a65f4d1adc2bf76578c9dad4d3e77d70b4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php
@@ -0,0 +1,279 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductRepositoryInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products';
+
+    private $productData = [
+        [
+            ProductInterface::SKU => 'simple',
+            ProductInterface::NAME => 'Simple Related Product',
+            ProductInterface::TYPE_ID => 'simple',
+            ProductInterface::PRICE => 10,
+        ],
+        [
+            ProductInterface::SKU => 'simple_with_cross',
+            ProductInterface::NAME => 'Simple Product With Related Product',
+            ProductInterface::TYPE_ID => 'simple',
+            ProductInterface::PRICE => 10
+        ],
+    ];
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_related.php
+     */
+    public function testGet()
+    {
+        $productData = $this->productData[0];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productData[ProductInterface::SKU],
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, ['productSku' => $productData[ProductInterface::SKU]]);
+        foreach ([ProductInterface::SKU, ProductInterface::NAME, ProductInterface::PRICE] as $key) {
+            $this->assertEquals($productData[$key], $response[$key]);
+        }
+    }
+
+    public function testGetNoSuchEntityException()
+    {
+        $invalidSku = '(nonExistingSku)';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $invalidSku,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $expectedMessage = 'Requested product doesn\'t exist';
+
+        try {
+            $this->_webApiCall($serviceInfo, ['productSku' => $invalidSku]);
+            $this->fail("Expected throwing exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function productCreationProvider()
+    {
+        $productBuilder = function ($data) {
+            return array_replace_recursive(
+                $this->getSimpleProductData(),
+                $data
+            );
+        };
+        return [
+            [$productBuilder([ProductInterface::TYPE_ID => 'simple', ProductInterface::SKU => 'psku-test-1'])],
+            [$productBuilder([ProductInterface::TYPE_ID => 'virtual', ProductInterface::SKU => 'psku-test-2'])],
+        ];
+    }
+
+    /**
+     * @dataProvider productCreationProvider
+     */
+    public function testCreate($product)
+    {
+        $response = $this->saveProduct($product);
+        $this->assertArrayHasKey(ProductInterface::SKU, $response);
+        $this->deleteProduct($product[ProductInterface::SKU]);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testUpdate()
+    {
+        $productData = [
+            ProductInterface::NAME => 'Very Simple Product', //new name
+            ProductInterface::SKU => 'simple', //sku from fixture
+        ];
+        $product = $this->getSimpleProductData($productData);
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+            $product[ProductInterface::SKU] = null;
+        }
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productData[ProductInterface::SKU],
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = ['product' => $product];
+        $response =  $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertArrayHasKey(ProductInterface::SKU, $response);
+        $this->assertArrayHasKey(ProductInterface::NAME, $response);
+        $this->assertEquals($productData[ProductInterface::NAME], $response[ProductInterface::NAME]);
+        $this->assertEquals($productData[ProductInterface::SKU], $response[ProductInterface::SKU]);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testDelete()
+    {
+        $response = $this->deleteProduct('simple');
+        $this->assertTrue($response);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'sku',
+                                'value' => 'simple',
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['sku']);
+        $this->assertEquals('simple', $response['items'][0]['sku']);
+    }
+
+    /**
+     * Get Simple Product Data
+     *
+     * @param array $productData
+     * @return array
+     */
+    protected function getSimpleProductData($productData = [])
+    {
+        return [
+            ProductInterface::SKU => isset($productData[ProductInterface::SKU])
+                ? $productData[ProductInterface::SKU] : uniqid('sku-', true),
+            ProductInterface::NAME => isset($productData[ProductInterface::NAME])
+                ? $productData[ProductInterface::NAME] : uniqid('sku-', true),
+            ProductInterface::VISIBILITY => 4,
+            ProductInterface::TYPE_ID => 'simple',
+            ProductInterface::PRICE => 3.62,
+            ProductInterface::STATUS => 1,
+            ProductInterface::TYPE_ID => 'simple',
+            ProductInterface::ATTRIBUTE_SET_ID => 4,
+            'custom_attributes' => [
+                ['attribute_code' => 'cost', 'value' => ''],
+                ['attribute_code' => 'description', 'value' => 'Description'],
+            ]
+        ];
+    }
+
+    /**
+     * @param $product
+     * @return mixed
+     */
+    protected function saveProduct($product)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = ['product' => $product];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * Delete Product
+     *
+     * @param string $sku
+     * @return boolean
+     */
+    protected function deleteProduct($sku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $sku,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+
+        return (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ?
+            $this->_webApiCall($serviceInfo, ['productSku' => $sku]) : $this->_webApiCall($serviceInfo);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTierPriceManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTierPriceManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..04f3d9c3d447f46be7318e207586eedf1134edef
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTierPriceManagementTest.php
@@ -0,0 +1,205 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductTierPriceManagementTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductTierPriceManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @dataProvider getListDataProvider
+     */
+    public function testGetList($customerGroupId, $count, $value, $qty)
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/group-prices/' . $customerGroupId . '/tiers',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $groupPriceList = $this->_webApiCall(
+                $serviceInfo,
+                ['productSku' => $productSku, 'customerGroupId' => $customerGroupId]
+            );
+
+        $this->assertCount($count, $groupPriceList);
+        if ($count) {
+            $this->assertEquals($value, $groupPriceList[0]['value']);
+            $this->assertEquals($qty, $groupPriceList[0]['qty']);
+        }
+    }
+
+    public function getListDataProvider()
+    {
+        return [
+            [0, 1, 5, 3],
+            [1, 0, null, null],
+            ['all', 2, 8, 2],
+        ];
+    }
+
+    /**
+     * @param string|int $customerGroupId
+     * @param int $qty
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @dataProvider deleteDataProvider
+     */
+    public function testDelete($customerGroupId, $qty)
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' =>   self::RESOURCE_PATH
+                    . $productSku . "/group-prices/" . $customerGroupId . "/tiers/" . $qty,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Remove',
+            ],
+        ];
+        $requestData = ['productSku' => $productSku, 'customerGroupId' => $customerGroupId, 'qty' => $qty];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    public function deleteDataProvider()
+    {
+        return [
+            'delete_tier_price_for_specific_customer_group' => [0, 3],
+            'delete_tier_price_for_all_customer_group' => ['all', 5]
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoAppIsolation enabled
+     */
+    public function testAdd()
+    {
+        $productSku = 'simple';
+        $customerGroupId = 1;
+        $qty = 50;
+        $price = 10;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku
+                    . '/group-prices/' . $customerGroupId . '/tiers/' . $qty . '/price/' . $price,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Add',
+            ],
+        ];
+
+        $requestData = [
+            'productSku' => $productSku,
+            'customerGroupId' => $customerGroupId,
+            'qty' => $qty,
+            'price' => $price,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Api\ProductTierPriceManagementInterface $service */
+        $service = $objectManager->get('Magento\Catalog\Api\ProductTierPriceManagementInterface');
+        $prices = $service->getList($productSku, 1);
+        $this->assertCount(1, $prices);
+        $this->assertEquals(10, $prices[0]->getValue());
+        $this->assertEquals(50, $prices[0]->getQty());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoAppIsolation enabled
+     */
+    public function testAddWithAllCustomerGrouped()
+    {
+        $productSku = 'simple';
+        $customerGroupId = 'all';
+        $qty = 50;
+        $price = 20;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku
+                    . '/group-prices/' . $customerGroupId . '/tiers/' . $qty . '/price/' . $price,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Add',
+            ],
+        ];
+        $requestData = [
+            'productSku' => $productSku,
+            'customerGroupId' => $customerGroupId,
+            'qty' => $qty,
+            'price' => $price,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Api\ProductTierPriceManagementInterface $service */
+        $service = $objectManager->get('Magento\Catalog\Api\ProductTierPriceManagementInterface');
+        $prices = $service->getList($productSku, 'all');
+        $this->assertCount(3, $prices);
+        $this->assertEquals(20, (int)$prices[2]->getValue());
+        $this->assertEquals(50, (int)$prices[2]->getQty());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoAppIsolation enabled
+     */
+    public function testUpdateWithAllGroups()
+    {
+        $productSku = 'simple';
+        $customerGroupId = 'all';
+        $qty = 2;
+        $price = 20;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $productSku
+                    . '/group-prices/' . $customerGroupId . '/tiers/' . $qty . '/price/' . $price,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Add',
+            ],
+        ];
+        $requestData = [
+            'productSku' => $productSku,
+            'customerGroupId' => $customerGroupId,
+            'qty' => $qty,
+            'price' => $price,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        $objectManager = \Magento\TestFramework\ObjectManager::getInstance();
+        /** @var \Magento\Catalog\Api\ProductTierPriceManagementInterface $service */
+        $service = $objectManager->get('Magento\Catalog\Api\ProductTierPriceManagementInterface');
+        $prices = $service->getList($productSku, 'all');
+        $this->assertCount(2, $prices);
+        $this->assertEquals(20, (int)$prices[0]->getValue());
+        $this->assertEquals(2, (int)$prices[0]->getQty());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTypeListTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTypeListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..da15ba53f9221093f39b9154879fe9f8bddc1f9c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTypeListTest.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Catalog\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductTypeListTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductTypeListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    public function testGetProductTypes()
+    {
+        $expectedProductTypes = [
+            [
+                'name' => 'simple',
+                'label' => 'Simple Product',
+            ],
+            [
+                'name' => 'virtual',
+                'label' => 'Virtual Product',
+            ],
+            [
+                'name' => 'downloadable',
+                'label' => 'Downloadable Product',
+            ],
+            [
+                'name' => 'bundle',
+                'label' => 'Bundle Product',
+            ],
+            [
+                'name' => 'configurable',
+                'label' => 'Configurable Product',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/types',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetProductTypes',
+            ],
+        ];
+
+        $productTypes = $this->_webApiCall($serviceInfo);
+
+        foreach ($expectedProductTypes as $expectedProductType) {
+            $this->assertContains($expectedProductType, $productTypes);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options.php
new file mode 100644
index 0000000000000000000000000000000000000000..a302a11ae9388df415cb27d9f667edc997149ab0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+return [
+    [
+        'title' => 'test_option_code_1',
+        'type' => 'field',
+        'sort_order' => 1,
+        'is_require' => 1,
+        'price' => 10,
+        'price_type' => 'fixed',
+        'sku' => 'sku1',
+        'max_characters' => 10,
+        'values' => [],
+    ],
+    [
+        'title' => 'area option',
+        'type' => 'area',
+        'sort_order' => 2,
+        'is_require' => 0,
+        'price' => 20,
+        'price_type' => 'percent',
+        'sku' => 'sku2',
+        'max_characters' => 20,
+        'values' => []
+    ],
+    [
+        'title' => 'file option',
+        'type' => 'file',
+        'sort_order' => 3,
+        'is_require' => 1,
+        'price' => 30,
+        'price_type' => 'percent',
+        'sku' => 'sku3',
+        'file_extension' => 'jpg, png, gif',
+        'image_size_x' => 10,
+        'image_size_y' => 20,
+        'values' => []
+    ],
+    [
+        'title' => 'drop_down option',
+        'type' => 'drop_down',
+        'sort_order' => 4,
+        'is_require' => 1,
+        'values' => [
+            [
+                'title' => 'drop_down option 1',
+                'sort_order' => 1,
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'drop_down option 1 sku',
+
+            ],
+            [
+                'title' => 'drop_down option 2',
+                'sort_order' => 2,
+                'price' => 20,
+                'price_type' => 'fixed',
+                'sku' => 'drop_down option 2 sku'
+            ],
+        ],
+    ],
+    [
+        'title' => 'radio option',
+        'type' => 'radio',
+        'sort_order' => 5,
+        'is_require' => 1,
+        'values' => [
+            [
+                'title' => 'radio option 1',
+                'sort_order' => 1,
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'radio option 1 sku',
+            ],
+            [
+                'title' => 'radio option 2',
+                'sort_order' => 2,
+                'price' => 20,
+                'price_type' => 'fixed',
+                'sku' => 'radio option 2 sku',
+            ],
+        ],
+    ],
+    [
+        'title' => 'checkbox option',
+        'type' => 'checkbox',
+        'sort_order' => 6,
+        'is_require' => 1,
+        'values' => [
+            [
+                'title' => 'checkbox option 1',
+                'sort_order' => 1,
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'checkbox option 1 sku',
+            ],
+            [
+                'title' => 'checkbox option 2',
+                'sort_order' => 2,
+                'price' => 20,
+                'price_type' => 'fixed',
+                'sku' => 'checkbox option 2 sku'
+            ],
+        ],
+    ],
+    [
+        'title' => 'multiple option',
+        'type' => 'multiple',
+        'sort_order' => 7,
+        'is_require' => 1,
+        'values' => [
+            [
+                'title' => 'multiple option 1',
+                'sort_order' => 1,
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'multiple option 1 sku',
+            ],
+            [
+                'title' => 'multiple option 2',
+                'sort_order' => 2,
+                'price' => 20,
+                'price_type' => 'fixed',
+                'sku' => 'multiple option 2 sku'
+            ],
+        ],
+    ],
+    [
+        'title' => 'date option',
+        'type' => 'date',
+        'is_require' => 1,
+        'sort_order' => 8,
+        'price' => 80.0,
+        'price_type' => 'fixed',
+        'sku' => 'date option sku',
+        'values' => []
+
+    ],
+    [
+        'title' => 'date_time option',
+        'type' => 'date_time',
+        'is_require' => 1,
+        'sort_order' => 9,
+        'price' => 90.0,
+        'price_type' => 'fixed',
+        'sku' => 'date_time option sku',
+        'values' => []
+    ],
+    [
+        'title' => 'time option',
+        'type' => 'time',
+        'is_require' => 1,
+        'sort_order' => 10,
+        'price' => 100.0,
+        'price_type' => 'fixed',
+        'sku' => 'time option sku',
+        'values' => []
+    ],
+];
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_negative.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_negative.php
new file mode 100644
index 0000000000000000000000000000000000000000..24fb82474ec0acce36ff5e886f657bb29730a276
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/product_options_negative.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+return [
+    'empty_required_field' => [
+        'title' => '',
+        'type' => 'field',
+        'sort_order' => 1,
+        'is_require' => 1,
+        'price' => 10,
+        'price_type' => 'fixed',
+        'sku' => 'sku1',
+        'max_characters' => 10,
+    ],
+    'negative_price' => [
+        'title' => 'area option',
+        'type' => 'area',
+        'sort_order' => 2,
+        'is_require' => 0,
+        'price' => -20,
+        'price_type' => 'percent',
+        'sku' => 'sku2',
+        'max_characters' => 20,
+
+    ],
+    'negative_value_of_image_size' => [
+        'title' => 'file option',
+        'type' => 'file',
+        'sort_order' => 3,
+        'is_require' => 1,
+        'price' => 30,
+        'price_type' => 'percent',
+        'sku' => 'sku3',
+        'file_extension' => 'jpg',
+        'image_size_x' => -10,
+        'image_size_y' => -20,
+    ],
+    'option_with_type_select_without_options' => [
+        'title' => 'drop_down option',
+        'type' => 'drop_down',
+        'sort_order' => 4,
+        'is_require' => 1,
+    ],
+    'title_is_empty' => [
+        'title' => 'radio option',
+        'type' => 'radio',
+        'sort_order' => 5,
+        'is_require' => 1,
+        'values' => [
+            [
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'radio option 1 sku',
+                'title' => '',
+                'sort_order' => 1,
+            ],
+        ],
+    ],
+    'option_with_non_existing_price_type' => [
+        'title' => 'checkbox option',
+        'type' => 'checkbox',
+        'sort_order' => 6,
+        'is_require' => 1,
+        'values' => [
+            [
+                'price' => 10,
+                'price_type' => 'fixed_one',
+                'sku' => 'checkbox option 1 sku',
+                'title' => 'checkbox option 1',
+                'sort_order' => 1,
+            ],
+        ],
+    ],
+    'option_with_non_existing_option_type' => [
+        'title' => 'multiple option',
+        'type' => 'multiple_some_value',
+        'sort_order' => 7,
+        'is_require' => 1,
+        'values' => [
+            [
+                'price' => 10,
+                'price_type' => 'fixed',
+                'sku' => 'multiple option 1 sku',
+                'title' => 'multiple option 1',
+                'sort_order' => 1,
+            ],
+        ],
+    ],
+];
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/test_image.jpg b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/test_image.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ad6b747f73dd9d20f73b8fc780e74d1ff7952762
Binary files /dev/null and b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/_files/test_image.jpg differ
diff --git a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/LowStockItemsTest.php b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/LowStockItemsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..67c42fe79b822a94d69b605b2a3bb5496bd9a0a4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/LowStockItemsTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\CatalogInventory\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class LowStockItemsTest
+ */
+class LowStockItemsTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/stockItem/lowStock/';
+
+    /**
+     * @param float $qty
+     * @param int $currentPage
+     * @param int $pageSize
+     * @param array $result
+     * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php
+     * @dataProvider getLowStockItemsDataProvider
+     */
+    public function testGetLowStockItems($qty, $currentPage, $pageSize, $result)
+    {
+        $requestData = ['websiteId' => 1, 'qty' => $qty, 'pageSize' => $pageSize, 'currentPage' => $currentPage];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogInventoryStockRegistryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogInventoryStockRegistryV1GetLowStockItems',
+            ],
+        ];
+        $output = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertArrayHasKey('items', $output);
+    }
+
+    /**
+     * @return array
+     */
+    public function getLowStockItemsDataProvider()
+    {
+        return [
+            [
+                100,
+                1,
+                10,
+                [
+                    'search_criteria' => ['current_page' => 1, 'page_size' => 10, 'qty' => 100],
+                    'total_count' => 2,
+                    'items' => [
+                        [
+                            'product_id' => 10,
+                            'website_id' => 1,
+                            'stock_id' => 1,
+                            'qty' => 100,
+                            'stock_status' => null,
+                            'stock_item' => null,
+                        ],
+                        [
+                            'product_id' => 12,
+                            'website_id' => 1,
+                            'stock_id' => 1,
+                            'qty' => 140,
+                            'stock_status' => null,
+                            'stock_item' => null
+                        ],
+                    ]
+                ],
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bab5b01aa08d8c107023d11b69fe9d6a89037d42
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockItemTest.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\CatalogInventory\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * Class StockItemTest
+ */
+class StockItemTest extends WebapiAbstract
+{
+    /**
+     * Service name
+     */
+    const SERVICE_NAME = 'catalogInventoryStockItemApi';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Resource path
+     */
+    const RESOURCE_PATH = '/V1/stockItem';
+
+    /** @var \Magento\Catalog\Model\Resource\Product\Collection */
+    protected $productCollection;
+
+    /** @var \Magento\Framework\ObjectManagerInterface */
+    protected $objectManager;
+
+    /**
+     * Execute per test initialization
+     */
+    public function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->productCollection = $this->objectManager->get('Magento\Catalog\Model\Resource\Product\Collection');
+    }
+
+    /**
+     * Execute per test cleanup
+     */
+    public function tearDown()
+    {
+        /** @var \Magento\Framework\Registry $registry */
+        $registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', true);
+
+        $this->productCollection->addFieldToFilter('entity_id', ['in' => [10, 11, 12]])->delete();
+        unset($this->productCollection);
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', false);
+    }
+
+    /**
+     * @param array $result
+     * @return array
+     */
+    protected function getStockItemBySku($result)
+    {
+        $productSku = 'simple1';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$productSku",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogInventoryStockRegistryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogInventoryStockRegistryV1GetStockItemBySku',
+            ],
+        ];
+        $arguments = ['productSku' => $productSku];
+        $apiResult = $this->_webApiCall($serviceInfo, $arguments);
+        $result['item_id'] = $apiResult['item_id'];
+        $this->assertEquals($result, $apiResult, 'The stock data does not match.');
+        return $apiResult;
+    }
+
+    /**
+     * @param array $newData
+     * @param array $expectedResult
+     * @param array $fixtureData
+     * @magentoApiDataFixture Magento/Catalog/_files/multiple_products.php
+     * @dataProvider saveStockItemBySkuWithWrongInputDataProvider
+     */
+    public function testStockItemPUTWithWrongInput($newData, $expectedResult, $fixtureData)
+    {
+        $stockItemOld = $this->getStockItemBySku($fixtureData);
+        $productSku = 'simple1';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$productSku",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'catalogInventoryStockRegistryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogInventoryStockRegistryV1UpdateStockItemBySku',
+            ],
+        ];
+
+        $stockItemDetailsDo = $this->objectManager->get(
+            'Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder'
+        )->populateWithArray($newData)->create();
+        $arguments = ['productSku' => $productSku, 'stockItem' => $stockItemDetailsDo->getData()];
+        $this->assertEquals($stockItemOld['item_id'], $this->_webApiCall($serviceInfo, $arguments));
+
+        $stockItemFactory = $this->objectManager->get('Magento\CatalogInventory\Api\Data\StockItemInterfaceFactory');
+        $stockItem = $stockItemFactory->create();
+        $stockItemResource = $this->objectManager->get('Magento\CatalogInventory\Model\Resource\Stock\Item');
+        $stockItemResource->loadByProductId($stockItem, $stockItemOld['product_id'], $stockItemOld['website_id']);
+        $expectedResult['item_id'] = $stockItem->getItemId();
+        $this->assertEquals($expectedResult, $stockItem->getData());
+    }
+
+    /**
+     * @return array
+     */
+    public function saveStockItemBySkuWithWrongInputDataProvider()
+    {
+        return [
+            [
+                [
+                    'item_id' => 222,
+                    'product_id' => 222,
+                    'stock_id' => 1,
+                    'website_id' => 1,
+                    'qty' => '111.0000',
+                    'min_qty' => '0.0000',
+                    'use_config_min_qty' => 1,
+                    'is_qty_decimal' => 0,
+                    'backorders' => 0,
+                    'use_config_backorders' => 1,
+                    'min_sale_qty' => '1.0000',
+                    'use_config_min_sale_qty' => 1,
+                    'max_sale_qty' => '0.0000',
+                    'use_config_max_sale_qty' => 1,
+                    'is_in_stock' => 1,
+                    'low_stock_date' => '',
+                    'notify_stock_qty' => NULL,
+                    'use_config_notify_stock_qty' => 1,
+                    'manage_stock' => 0,
+                    'use_config_manage_stock' => 1,
+                    'stock_status_changed_auto' => 0,
+                    'use_config_qty_increments' => 1,
+                    'qty_increments' => '0.0000',
+                    'use_config_enable_qty_inc' => 1,
+                    'enable_qty_increments' => 0,
+                    'is_decimal_divided' => 0,
+                    'show_default_notification_message' => false,
+                ],
+                [
+                    'item_id' => '1',
+                    'product_id' => '10',
+                    'stock_id' => '1',
+                    'qty' => '111.0000',
+                    'min_qty' => '0.0000',
+                    'use_config_min_qty' => '1',
+                    'is_qty_decimal' => '0',
+                    'backorders' => '0',
+                    'use_config_backorders' => '1',
+                    'min_sale_qty' => '1.0000',
+                    'use_config_min_sale_qty' => '1',
+                    'max_sale_qty' => '0.0000',
+                    'use_config_max_sale_qty' => '1',
+                    'is_in_stock' => '1',
+                    'low_stock_date' => NULL,
+                    'notify_stock_qty' => NULL,
+                    'use_config_notify_stock_qty' => '1',
+                    'manage_stock' => '0',
+                    'use_config_manage_stock' => '1',
+                    'stock_status_changed_auto' => '0',
+                    'use_config_qty_increments' => '1',
+                    'qty_increments' => '0.0000',
+                    'use_config_enable_qty_inc' => '1',
+                    'enable_qty_increments' => '0',
+                    'is_decimal_divided' => '0',
+                    'website_id' => '1',
+                    'type_id' => 'simple',
+                ],
+                [
+                    'item_id' => 1,
+                    'product_id' => 10,
+                    'website_id' => 1,
+                    'stock_id' => 1,
+                    'qty' => 100,
+                    'is_in_stock' => 1,
+                    'is_qty_decimal' => '',
+                    'show_default_notification_message' => '',
+                    'use_config_min_qty' => 1,
+                    'min_qty' => 0,
+                    'use_config_min_sale_qty' => 1,
+                    'min_sale_qty' => 1,
+                    'use_config_max_sale_qty' => 1,
+                    'max_sale_qty' => 10000,
+                    'use_config_backorders' => 1,
+                    'backorders' => 0,
+                    'use_config_notify_stock_qty' => 1,
+                    'notify_stock_qty' => 1,
+                    'use_config_qty_increments' => 1,
+                    'qty_increments' => 0,
+                    'use_config_enable_qty_inc' => 1,
+                    'enable_qty_increments' => '',
+                    'use_config_manage_stock' => 1,
+                    'manage_stock' => 1,
+                    'low_stock_date' => 0,
+                    'is_decimal_divided' => '',
+                    'stock_status_changed_auto' => 0
+                ],
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockStatusTest.php b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockStatusTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ab00d4b085b5313427d6828afdbc5863317d092
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/StockStatusTest.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\CatalogInventory\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class StockStatusTest
+ */
+class StockStatusTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/stockStatus';
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testGetProductStockStatus()
+    {
+        $productSku = 'simple';
+        $objectManager = Bootstrap::getObjectManager();
+
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = $objectManager->get('Magento\Catalog\Model\Product')->load(1);
+        $expectedData = $product->getQuantityAndStockStatus();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$productSku",
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'catalogInventoryStockRegistryV1',
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'catalogInventoryStockRegistryV1GetStockStatusBySku',
+            ],
+        ];
+
+        $requestData = ['productSku' => $productSku];
+        $actualData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertArrayHasKey('stock_item', $actualData);
+        $this->assertEquals($expectedData['is_in_stock'], $actualData['stock_item']['is_in_stock']);
+        $this->assertEquals($expectedData['qty'], $actualData['stock_item']['qty']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..961d7caf314fc7b61cd83da7cc945bbbe7dc006f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/ReadServiceTest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Address\Billing;
+
+use Magento\Checkout\Service\V1\Data\Cart\Address;
+use Magento\Checkout\Service\V1\Data\Cart\Address\Region;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutAddressBillingReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testGetAddress()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+
+        /** @var \Magento\Sales\Model\Quote\Address $address */
+        $address = $quote->getBillingAddress();
+
+        $data = [
+            Address::KEY_COUNTRY_ID => $address->getCountryId(),
+            Address::KEY_ID => (int)$address->getId(),
+            Address::KEY_CUSTOMER_ID => $address->getCustomerId(),
+            Address::KEY_REGION => [
+                Region::REGION => $address->getRegion(),
+                Region::REGION_ID => $address->getRegionId(),
+                Region::REGION_CODE => $address->getRegionCode(),
+            ],
+            Address::KEY_STREET => $address->getStreet(),
+            Address::KEY_COMPANY => $address->getCompany(),
+            Address::KEY_TELEPHONE => $address->getTelephone(),
+            Address::KEY_POSTCODE => $address->getPostcode(),
+            Address::KEY_CITY => $address->getCity(),
+            Address::KEY_FIRSTNAME => $address->getFirstname(),
+            Address::KEY_LASTNAME => $address->getLastname(),
+            Address::KEY_EMAIL => $address->getEmail(),
+            Address::CUSTOM_ATTRIBUTES_KEY => [['attribute_code' => 'disable_auto_group_change', 'value' => null]],
+        ];
+
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/billing-address',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAddress',
+            ],
+        ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            unset($data[Address::KEY_PREFIX]);
+            unset($data[Address::KEY_SUFFIX]);
+            unset($data[Address::KEY_MIDDLENAME]);
+            unset($data[Address::KEY_FAX]);
+            unset($data[Address::KEY_VAT_ID]);
+        }
+
+        $requestData = ["cartId" => $cartId];
+        $this->assertEquals($data, $this->_webApiCall($serviceInfo, $requestData));
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d69ab59b5d99cb1dee9fee7af0b62886a67d741b
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Address\Billing;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutAddressBillingWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Checkout\Service\V1\Data\Cart\AddressBuilder
+     */
+    protected $builder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Checkout\Service\V1\Data\Cart\AddressBuilder');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testSetAddress()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $quote->getId() . '/billing-address',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetAddress',
+            ],
+        ];
+
+        $addressData = [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'email' => 'cat@dog.com',
+            'company' => 'eBay Inc',
+            'street' => ['Typical Street', 'Tiny House 18'],
+            'city' => 'Big City',
+            'region' => [
+                'region_id' => 12,
+                'region' => 'California',
+                'region_code' => 'CA',
+            ],
+            'postcode' => '0985432',
+            'country_id' => 'US',
+            'telephone' => '88776655',
+            'fax' => '44332255',
+        ];
+        $requestData = [
+            "cartId" => $quote->getId(),
+            'addressData' => $addressData,
+        ];
+
+        $addressId = $this->_webApiCall($serviceInfo, $requestData);
+
+        //reset $quote to reload data
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $savedData  = $quote->getBillingAddress()->getData();
+        $this->assertEquals($addressId, $savedData['address_id']);
+        //custom checks for street, region and address_type
+        foreach ($addressData['street'] as $streetLine) {
+            $this->assertContains($streetLine, $quote->getBillingAddress()->getStreet());
+        }
+        unset($addressData['street']);
+        $this->assertEquals($addressData['region']['region_id'], $savedData['region_id']);
+        $this->assertEquals($addressData['region']['region'], $savedData['region']);
+        unset($addressData['region']);
+        $this->assertEquals('billing', $savedData['address_type']);
+        //check the rest of fields
+        foreach ($addressData as $key => $value) {
+            $this->assertEquals($value, $savedData[$key]);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..da2908227abafe78327683472aa43680bfb6e955
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/ReadServiceTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Address\Shipping;
+
+use Magento\Checkout\Service\V1\Data\Cart\Address;
+use Magento\Checkout\Service\V1\Data\Cart\Address\Region;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutAddressShippingReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testGetAddress()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+
+        /** @var \Magento\Sales\Model\Quote\Address  $address */
+        $address = $quote->getShippingAddress();
+
+        $data = [
+            Address::KEY_COUNTRY_ID => $address->getCountryId(),
+            Address::KEY_ID => (int)$address->getId(),
+            Address::KEY_CUSTOMER_ID => $address->getCustomerId(),
+            Address::KEY_REGION => [
+                Region::REGION => $address->getRegion(),
+                Region::REGION_ID => $address->getRegionId(),
+                Region::REGION_CODE => $address->getRegionCode(),
+            ],
+            Address::KEY_STREET => $address->getStreet(),
+            Address::KEY_COMPANY => $address->getCompany(),
+            Address::KEY_TELEPHONE => $address->getTelephone(),
+            Address::KEY_POSTCODE => $address->getPostcode(),
+            Address::KEY_CITY => $address->getCity(),
+            Address::KEY_FIRSTNAME => $address->getFirstname(),
+            Address::KEY_LASTNAME => $address->getLastname(),
+            Address::KEY_EMAIL => $address->getEmail(),
+            Address::CUSTOM_ATTRIBUTES_KEY => [['attribute_code' => 'disable_auto_group_change', 'value' => null]],
+        ];
+
+        $cartId = $quote->getId();
+
+        $serviceInfo = $this->getServiceInfo();
+        $serviceInfo['rest']['resourcePath'] = str_replace('{cart_id}', $cartId, $serviceInfo['rest']['resourcePath']);
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            unset($data[Address::KEY_PREFIX]);
+            unset($data[Address::KEY_SUFFIX]);
+            unset($data[Address::KEY_MIDDLENAME]);
+            unset($data[Address::KEY_FAX]);
+            unset($data[Address::KEY_VAT_ID]);
+        }
+
+        $requestData = ["cartId" => $cartId];
+        $this->assertEquals($data, $this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
+     *
+     * @expectedException \Exception
+     * @expectedExceptionMessage Cart contains virtual product(s) only. Shipping address is not applicable
+     */
+    public function testGetAddressOfQuoteWithVirtualProduct()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $cartId = $quote->load('test_order_with_virtual_product', 'reserved_order_id')->getId();
+
+        $serviceInfo = $this->getServiceInfo();
+        $serviceInfo['rest']['resourcePath'] = str_replace('{cart_id}', $cartId, $serviceInfo['rest']['resourcePath']);
+
+        $this->_webApiCall($serviceInfo, ["cartId" => $cartId]);
+    }
+
+    /**
+     * @return array
+     */
+    protected function getServiceInfo()
+    {
+        return $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '{cart_id}/shipping-address',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAddress',
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a8e322508d99d34ad92bdf17d759094fe96af86
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Address\Shipping;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutAddressShippingWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Checkout\Service\V1\Data\Cart\AddressBuilder
+     */
+    protected $builder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Checkout\Service\V1\Data\Cart\AddressBuilder');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testSetAddress()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $quote->getId() . '/shipping-address',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetAddress',
+            ],
+        ];
+
+        $addressData = [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'email' => 'cat@dog.com',
+            'company' => 'eBay Inc',
+            'street' => ['Typical Street', 'Tiny House 18'],
+            'city' => 'Big City',
+            'region' => [
+                'region_id' => 12,
+                'region' => 'California',
+                'region_code' => 'CA',
+            ],
+            'postcode' => '0985432',
+            'country_id' => 'US',
+            'telephone' => '88776655',
+            'fax' => '44332255',
+        ];
+        $requestData = [
+            "cartId" => $quote->getId(),
+            'addressData' => $addressData,
+        ];
+
+        $addressId = $this->_webApiCall($serviceInfo, $requestData);
+
+        //reset $quote to reload data
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $savedData  = $quote->getShippingAddress()->getData();
+        $this->assertEquals($addressId, $savedData['address_id']);
+        $this->assertEquals(0, $savedData['same_as_billing']);
+        //custom checks for street, region and address_type
+        $this->assertEquals($addressData['street'], $quote->getShippingAddress()->getStreet());
+        unset($addressData['street']);
+        $this->assertEquals($addressData['region']['region_id'], $savedData['region_id']);
+        $this->assertEquals($addressData['region']['region'], $savedData['region']);
+        unset($addressData['region']);
+        $this->assertEquals('shipping', $savedData['address_type']);
+        //check the rest of fields
+        foreach ($addressData as $key => $value) {
+            $this->assertEquals($value, $savedData[$key]);
+        }
+    }
+
+    /**
+     * Set address to quote with virtual products only
+     *
+     * @expectedException \Exception
+     * @expectedExceptionMessage Cart contains virtual product(s) only. Shipping address is not applicable
+     *
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
+     */
+    public function testSetAddressForVirtualQuote()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_with_virtual_product', 'reserved_order_id');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $quote->getId() . '/shipping-address',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetAddress',
+            ],
+        ];
+
+        $addressData = [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'email' => 'cat@dog.com',
+            'company' => 'eBay Inc',
+            'street' => ['Typical Street', 'Tiny House 18'],
+            'city' => 'Big City',
+            'region' => [
+                'region_id' => 12,
+                'region' => 'California',
+                'region_code' => 'CA',
+            ],
+            'postcode' => '0985432',
+            'country_id' => 'US',
+            'telephone' => '88776655',
+            'fax' => '44332255',
+        ];
+        $requestData = [
+            "cartId" => $quote->getId(),
+            'addressData' => $addressData,
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d2f8063b359c9c231a6ebdff9149f469ce46183
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php
@@ -0,0 +1,297 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Checkout\Service\V1\Cart;
+
+use Magento\Checkout\Service\V1\Data\Cart;
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\SearchCriteria;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\TestFramework\ObjectManager;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * @var SearchCriteriaBuilder
+     */
+    private $searchBuilder;
+
+    /**
+     * @var SortOrderBuilder
+     */
+    private $sortOrderBuilder;
+
+    /**
+     * @var FilterBuilder
+     */
+    private $filterBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+        $this->sortOrderBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SortOrderBuilder'
+        );
+        $this->searchBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+    }
+
+    protected function tearDown()
+    {
+        try {
+            $cart = $this->getCart('test01');
+            $cart->delete();
+        } catch (\InvalidArgumentException $e) {
+            // Do nothing if cart fixture was not used
+        }
+        parent::tearDown();
+    }
+
+    /**
+     * Retrieve quote by given reserved order ID
+     *
+     * @param string $reservedOrderId
+     * @return \Magento\Sales\Model\Quote
+     * @throws \InvalidArgumentException
+     */
+    protected function getCart($reservedOrderId)
+    {
+        /** @var $cart \Magento\Sales\Model\Quote */
+        $cart = $this->objectManager->get('Magento\Sales\Model\Quote');
+        $cart->load($reservedOrderId, 'reserved_order_id');
+        if (!$cart->getId()) {
+            throw new \InvalidArgumentException('There is no quote with provided reserved order ID.');
+        }
+        return $cart;
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     */
+    public function testGetCart()
+    {
+        $cart = $this->getCart('test01');
+        $cartId = $cart->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'checkoutCartReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartReadServiceV1GetCart',
+            ],
+        ];
+
+        $requestData = ['cartId' => $cartId];
+        $cartData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($cart->getId(), $cartData['id']);
+        $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
+        $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
+        $this->assertEquals($cart->getStoreId(), $cartData['store_id']);
+        $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
+        $this->assertEquals($cart->getIsVirtual(), $cartData['is_virtual']);
+        $this->assertEquals($cart->getOrigOrderId(), $cartData['orig_order_id']);
+        $this->assertEquals($cart->getItemsCount(), $cartData['items_count']);
+        $this->assertEquals($cart->getItemsQty(), $cartData['items_qty']);
+
+        $this->assertContains('customer', $cartData);
+        $this->assertEquals(1, $cartData['customer']['is_guest']);
+        $this->assertContains('totals', $cartData);
+        $this->assertEquals($cart->getSubtotal(), $cartData['totals']['subtotal']);
+        $this->assertEquals($cart->getGrandTotal(), $cartData['totals']['grand_total']);
+        $this->assertContains('currency', $cartData);
+        $this->assertEquals($cart->getGlobalCurrencyCode(), $cartData['currency']['global_currency_code']);
+        $this->assertEquals($cart->getBaseCurrencyCode(), $cartData['currency']['base_currency_code']);
+        $this->assertEquals($cart->getQuoteCurrencyCode(), $cartData['currency']['quote_currency_code']);
+        $this->assertEquals($cart->getStoreCurrencyCode(), $cartData['currency']['store_currency_code']);
+        $this->assertEquals($cart->getBaseToGlobalRate(), $cartData['currency']['base_to_global_rate']);
+        $this->assertEquals($cart->getBaseToQuoteRate(), $cartData['currency']['base_to_quote_rate']);
+        $this->assertEquals($cart->getStoreToBaseRate(), $cartData['currency']['store_to_base_rate']);
+        $this->assertEquals($cart->getStoreToQuoteRate(), $cartData['currency']['store_to_quote_rate']);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage No such entity with
+     */
+    public function testGetCartThrowsExceptionIfThereIsNoCartWithProvidedId()
+    {
+        $cartId = 9999;
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartReadServiceV1GetCart',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+
+        $requestData = ['cartId' => $cartId];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php
+     */
+    public function testGetCartForCustomer()
+    {
+        $cart = $this->getCart('test01');
+        $customerId = $cart->getCustomer()->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/customer/' . $customerId . '/cart',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'checkoutCartReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartReadServiceV1GetCartForCustomer',
+            ],
+        ];
+
+        $requestData = ['customerId' => $customerId];
+        $cartData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($cart->getId(), $cartData['id']);
+        $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
+        $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
+        $this->assertEquals($cart->getStoreId(), $cartData['store_id']);
+        $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
+        $this->assertEquals($cart->getIsVirtual(), $cartData['is_virtual']);
+        $this->assertEquals($cart->getOrigOrderId(), $cartData['orig_order_id']);
+        $this->assertEquals($cart->getItemsCount(), $cartData['items_count']);
+        $this->assertEquals($cart->getItemsQty(), $cartData['items_qty']);
+
+        $this->assertContains('customer', $cartData);
+        $this->assertEquals(0, $cartData['customer']['is_guest']);
+        $this->assertContains('totals', $cartData);
+        $this->assertEquals($cart->getSubtotal(), $cartData['totals']['subtotal']);
+        $this->assertEquals($cart->getGrandTotal(), $cartData['totals']['grand_total']);
+        $this->assertContains('currency', $cartData);
+        $this->assertEquals($cart->getGlobalCurrencyCode(), $cartData['currency']['global_currency_code']);
+        $this->assertEquals($cart->getBaseCurrencyCode(), $cartData['currency']['base_currency_code']);
+        $this->assertEquals($cart->getQuoteCurrencyCode(), $cartData['currency']['quote_currency_code']);
+        $this->assertEquals($cart->getStoreCurrencyCode(), $cartData['currency']['store_currency_code']);
+        $this->assertEquals($cart->getBaseToGlobalRate(), $cartData['currency']['base_to_global_rate']);
+        $this->assertEquals($cart->getBaseToQuoteRate(), $cartData['currency']['base_to_quote_rate']);
+        $this->assertEquals($cart->getStoreToBaseRate(), $cartData['currency']['store_to_base_rate']);
+        $this->assertEquals($cart->getStoreToQuoteRate(), $cartData['currency']['store_to_quote_rate']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     */
+    public function testGetCartList()
+    {
+        $cart = $this->getCart('test01');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/carts',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'checkoutCartReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartReadServiceV1GetCartList',
+            ],
+        ];
+
+        // The following two filters are used as alternatives. The target cart does not match the first one.
+        $grandTotalFilter = $this->filterBuilder->setField('grand_total')
+            ->setConditionType('gteq')
+            ->setValue(15)
+            ->create();
+        $subtotalFilter = $this->filterBuilder->setField('subtotal')
+            ->setConditionType('eq')
+            ->setValue($cart->getSubtotal())
+            ->create();
+
+        $yesterdayDate = (new \DateTime())->sub(new \DateInterval('P1D'))->format('Y-m-d');
+        $tomorrowDate = (new \DateTime())->add(new \DateInterval('P1D'))->format('Y-m-d');
+        $minCreatedAtFilter = $this->filterBuilder->setField(Cart::CREATED_AT)
+            ->setConditionType('gteq')
+            ->setValue($yesterdayDate)
+            ->create();
+        $maxCreatedAtFilter = $this->filterBuilder->setField(Cart::CREATED_AT)
+            ->setConditionType('lteq')
+            ->setValue($tomorrowDate)
+            ->create();
+
+        $this->searchBuilder->addFilter([$grandTotalFilter, $subtotalFilter]);
+        $this->searchBuilder->addFilter([$minCreatedAtFilter]);
+        $this->searchBuilder->addFilter([$maxCreatedAtFilter]);
+        /** @var SortOrder $sortOrder */
+        $sortOrder = $this->sortOrderBuilder->setField('subtotal')->setDirection(SearchCriteria::SORT_ASC)->create();
+        $this->searchBuilder->setSortOrders([$sortOrder]);
+        $searchCriteria = $this->searchBuilder->create()->__toArray();
+
+        $requestData = ['searchCriteria' => $searchCriteria];
+        $searchResult = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertArrayHasKey('total_count', $searchResult);
+        $this->assertEquals(1, $searchResult['total_count']);
+        $this->assertArrayHasKey('items', $searchResult);
+        $this->assertCount(1, $searchResult['items']);
+
+        $cartData = $searchResult['items'][0];
+        $this->assertEquals($cart->getId(), $cartData['id']);
+        $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
+        $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
+        $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
+        $this->assertEquals($cart->getStoreId(), $cartData['store_id']);
+
+        $this->assertContains('totals', $cartData);
+        $this->assertEquals($cart->getBaseSubtotal(), $cartData['totals']['base_subtotal']);
+        $this->assertEquals($cart->getBaseGrandTotal(), $cartData['totals']['base_grand_total']);
+        $this->assertContains('customer', $cartData);
+        $this->assertEquals(1, $cartData['customer']['is_guest']);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Field 'invalid_field' cannot be used for search.
+     */
+    public function testGetCartListThrowsExceptionIfProvidedSearchFieldIsInvalid()
+    {
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartReadServiceV1GetCartList',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $invalidFilter = $this->filterBuilder->setField('invalid_field')
+            ->setConditionType('eq')
+            ->setValue(0)
+            ->create();
+
+        $this->searchBuilder->addFilter([$invalidFilter]);
+        $searchCriteria = $this->searchBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchCriteria];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/TotalsServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/TotalsServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9c6a50f2d7e7249d1843797faede152509b29224
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/TotalsServiceTest.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Checkout\Service\V1\Cart;
+
+use Magento\Checkout\Service\V1\Data\Cart\Totals;
+use Magento\Checkout\Service\V1\Data\Cart\Totals\Item as ItemTotals;
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\TestFramework\ObjectManager;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class TotalsServiceTest extends WebapiAbstract
+{
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * @var SearchCriteriaBuilder
+     */
+    private $searchBuilder;
+
+    /**
+     * @var FilterBuilder
+     */
+    private $filterBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->searchBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_shipping_method.php
+     */
+    public function testGetTotals()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        /** @var \Magento\Sales\Model\Quote\Address $shippingAddress */
+        $shippingAddress = $quote->getShippingAddress();
+
+        $data = [
+            Totals::BASE_GRAND_TOTAL => $quote->getBaseGrandTotal(),
+            Totals::GRAND_TOTAL => $quote->getGrandTotal(),
+            Totals::BASE_SUBTOTAL => $quote->getBaseSubtotal(),
+            Totals::SUBTOTAL => $quote->getSubtotal(),
+            Totals::BASE_SUBTOTAL_WITH_DISCOUNT => $quote->getBaseSubtotalWithDiscount(),
+            Totals::SUBTOTAL_WITH_DISCOUNT => $quote->getSubtotalWithDiscount(),
+            Totals::DISCOUNT_AMOUNT => $shippingAddress->getDiscountAmount(),
+            Totals::BASE_DISCOUNT_AMOUNT => $shippingAddress->getBaseDiscountAmount(),
+            Totals::SHIPPING_AMOUNT => $shippingAddress->getShippingAmount(),
+            Totals::BASE_SHIPPING_AMOUNT => $shippingAddress->getBaseShippingAmount(),
+            Totals::SHIPPING_DISCOUNT_AMOUNT => $shippingAddress->getShippingDiscountAmount(),
+            Totals::BASE_SHIPPING_DISCOUNT_AMOUNT => $shippingAddress->getBaseShippingDiscountAmount(),
+            Totals::TAX_AMOUNT => $shippingAddress->getTaxAmount(),
+            Totals::BASE_TAX_AMOUNT => $shippingAddress->getBaseTaxAmount(),
+            Totals::SHIPPING_TAX_AMOUNT => $shippingAddress->getShippingTaxAmount(),
+            Totals::BASE_SHIPPING_TAX_AMOUNT => $shippingAddress->getBaseShippingTaxAmount(),
+            Totals::SUBTOTAL_INCL_TAX => $shippingAddress->getSubtotalInclTax(),
+            Totals::BASE_SUBTOTAL_INCL_TAX => $shippingAddress->getBaseSubtotalTotalInclTax(),
+            Totals::SHIPPING_INCL_TAX => $shippingAddress->getShippingInclTax(),
+            Totals::BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(),
+            Totals::BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(),
+            Totals::QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(),
+            Totals::ITEMS => [$this->getQuoteItemTotalsData($quote)],
+        ];
+
+        $requestData = ['cartId' => $cartId];
+
+        $data = $this->formatTotalsData($data);
+
+        $this->assertEquals($data, $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData));
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage No such entity
+     */
+    public function testGetTotalsWithAbsentQuote()
+    {
+        $cartId = 'unknownCart';
+        $requestData = ['cartId' => $cartId];
+        $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData);
+    }
+
+    /**
+     * Get service info for totals service
+     *
+     * @param string $cartId
+     * @return array
+     */
+    protected function getServiceInfoForTotalsService($cartId)
+    {
+        return [
+            'soap' => [
+                'service' => 'checkoutCartTotalsServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartTotalsServiceV1GetTotals',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId . '/totals',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+    }
+
+    /**
+     * Adjust response details for SOAP protocol
+     *
+     * @param array $data
+     * @return array
+     */
+    protected function formatTotalsData($data)
+    {
+        foreach ($data as $key => $field) {
+            if (is_numeric($field)) {
+                $data[$key] = round($field, 1);
+                if ($data[$key] === null) {
+                    $data[$key] = 0.0;
+                }
+            }
+        }
+
+        unset($data[Totals::BASE_SUBTOTAL_INCL_TAX]);
+
+        return $data;
+    }
+
+    /**
+     * Fetch quote item totals data from quote
+     *
+     * @param \Magento\Sales\Model\Quote $quote
+     * @return array
+     */
+    protected function getQuoteItemTotalsData(\Magento\Sales\Model\Quote $quote)
+    {
+        $items = $quote->getAllItems();
+        $item = array_shift($items);
+
+        return [
+            ItemTotals::PRICE => $item->getPrice(),
+            ItemTotals::BASE_PRICE => $item->getBasePrice(),
+            ItemTotals::QTY => $item->getQty(),
+            ItemTotals::ROW_TOTAL => $item->getRowTotal(),
+            ItemTotals::BASE_ROW_TOTAL => $item->getBaseRowTotal(),
+            ItemTotals::ROW_TOTAL_WITH_DISCOUNT => $item->getRowTotalWithDiscount(),
+            ItemTotals::TAX_AMOUNT => $item->getTaxAmount(),
+            ItemTotals::BASE_TAX_AMOUNT => $item->getBaseTaxAmount(),
+            ItemTotals::TAX_PERCENT => $item->getTaxPercent(),
+            ItemTotals::DISCOUNT_AMOUNT => $item->getDiscountAmount(),
+            ItemTotals::BASE_DISCOUNT_AMOUNT => $item->getBaseDiscountAmount(),
+            ItemTotals::DISCOUNT_PERCENT => $item->getDiscountPercent(),
+            ItemTotals::PRICE_INCL_TAX => $item->getPriceInclTax(),
+            ItemTotals::BASE_PRICE_INCL_TAX => $item->getBasePriceInclTax(),
+            ItemTotals::ROW_TOTAL_INCL_TAX => $item->getRowTotalInclTax(),
+            ItemTotals::BASE_ROW_TOTAL_INCL_TAX => $item->getBaseRowTotalInclTax(),
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..781ce89f50be79a94b2cf8d44595ef5f7db2b797
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php
@@ -0,0 +1,299 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Cart;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutCartWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    protected $createdQuotes = [];
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    public function testCreate()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Create',
+            ],
+        ];
+
+        $quoteId = $this->_webApiCall($serviceInfo);
+        $this->assertGreaterThan(0, $quoteId);
+        $this->createdQuotes[] = $quoteId;
+    }
+
+    public function tearDown()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        foreach ($this->createdQuotes as $quoteId) {
+            $quote->load($quoteId);
+            $quote->delete();
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     */
+    public function testAssignCustomer()
+    {
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+        $cartId = $quote->getId();
+        /** @var $repository \Magento\Customer\Api\CustomerRepositoryInterface */
+        $repository = $this->objectManager->create('Magento\Customer\Api\CustomerRepositoryInterface');
+        /** @var $customer \Magento\Customer\Api\Data\CustomerInterface */
+        $customer = $repository->getById(1);
+        $customerId = $customer->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+        // Cart must be anonymous (see fixture)
+        $this->assertEmpty($quote->getCustomerId());
+
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+        // Reload target quote
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+        $this->assertEquals(0, $quote->getCustomerIsGuest());
+        $this->assertEquals($customer->getId(), $quote->getCustomerId());
+        $this->assertEquals($customer->getFirstname(), $quote->getCustomerFirstname());
+        $this->assertEquals($customer->getLastname(), $quote->getCustomerLastname());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     * @expectedException \Exception
+     */
+    public function testAssignCustomerThrowsExceptionIfThereIsNoCustomerWithGivenId()
+    {
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $customerId = 9999;
+        $serviceInfo = [
+            'soap' => [
+                'serviceVersion' => 'V1',
+                'service' => 'checkoutCartWriteServiceV1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     * @expectedException \Exception
+     */
+    public function testAssignCustomerThrowsExceptionIfThereIsNoCartWithGivenId()
+    {
+        $cartId = 9999;
+        $customerId = 1;
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Cannot assign customer to the given cart. The cart is not anonymous.
+     */
+    public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous()
+    {
+        /** @var $customer \Magento\Customer\Model\Customer */
+        $customer = $this->objectManager->create('Magento\Customer\Model\Customer')->load(1);
+        $customerId = $customer->getId();
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+                'resourcePath' => '/V1/carts/' . $cartId,
+            ],
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer_non_default_website_id.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Cannot assign customer to the given cart. The cart belongs to different store.
+     */
+    public function testAssignCustomerThrowsExceptionIfCartIsAssignedToDifferentStore()
+    {
+        $repository = $this->objectManager->create('Magento\Customer\Api\CustomerRepositoryInterface');
+        /** @var $customer \Magento\Customer\Api\Data\CustomerInterface */
+        $customer = $repository->getById(1);
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+
+        $customerId = $customer->getId();
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+            ],
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+                'resourcePath' => '/V1/carts/' . $cartId,
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Cannot assign customer to the given cart. Customer already has active cart.
+     */
+    public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart()
+    {
+        /** @var $customer \Magento\Customer\Model\Customer */
+        $customer = $this->objectManager->create('Magento\Customer\Model\Customer')->load(1);
+        // Customer has a quote with reserved order ID test_order_1 (see fixture)
+        /** @var $customerQuote \Magento\Sales\Model\Quote */
+        $customerQuote = $this->objectManager->create('Magento\Sales\Model\Quote')
+            ->load('test_order_1', 'reserved_order_id');
+        $customerQuote->setIsActive(1)->save();
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test01', 'reserved_order_id');
+
+        $cartId = $quote->getId();
+        $customerId = $customer->getId();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'operation' => 'checkoutCartWriteServiceV1AssignCustomer',
+                'serviceVersion' => 'V1',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'customerId' => $customerId,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php
+     */
+    public function testOrderPlacesOrder()
+    {
+        /** @var $quote \Magento\Sales\Model\Quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote')->load('test_order_1', 'reserved_order_id');
+
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'checkoutCartWriteServiceV1',
+                'operation' => 'checkoutCartWriteServiceV1Order',
+                'serviceVersion' => 'V1',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $cartId . '/order',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order')->load(1);
+        $items = $order->getAllItems();
+        $this->assertCount(1, $items);
+        $this->assertEquals('Simple Product', $items[0]->getName());
+        $quote->delete();
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d36d4289fec3b938c49d92c19287d14b87dbb672
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Coupon;
+
+use Magento\Checkout\Service\V1\Data\Cart\Coupon as Coupon;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutCouponReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_coupon_saved.php
+     */
+    public function testGet()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $data = [
+            Coupon::COUPON_CODE => $quote->getCouponCode(),
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $this->assertEquals($data, $this->_webApiCall($serviceInfo, $requestData));
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6dfbf57eb0e4b5928db2d5e9b8b1e6cf9699270
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Coupon/WriteServiceTest.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Coupon;
+
+use Magento\Checkout\Service\V1\Data\Cart\Coupon;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutCouponWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_coupon_saved.php
+     */
+    public function testDelete()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons',
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Delete',
+            ],
+        ];
+        $requestData = ["cartId" => $cartId];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+        $quote->load('test_order_1', 'reserved_order_id');
+        $this->assertEquals('', $quote->getCouponCode());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Coupon code is not valid
+     */
+    public function testSetCouponThrowsExceptionIfCouponDoesNotExist()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Set',
+            ],
+        ];
+
+        $data = [Coupon::COUPON_CODE => 'invalid_coupon_code'];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "couponCodeData" => $data,
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/quote.php
+     * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent.php
+     */
+    public function testSetCouponSuccess()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test01', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/coupons',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Set',
+            ],
+        ];
+
+        $salesRule = $this->objectManager->create('Magento\SalesRule\Model\Rule');
+        $salesRule->load('Test Coupon', 'name');
+
+        $couponCode = $salesRule->getCouponCode();
+        $data = [Coupon::COUPON_CODE => $couponCode];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "couponCodeData" => $data,
+        ];
+
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+
+        $quoteWithCoupon = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quoteWithCoupon->load('test01', 'reserved_order_id');
+
+        $this->assertEquals($quoteWithCoupon->getCouponCode(), $couponCode);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f099951a762b2a8c7cf9468749002192b3909c4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/ReadServiceTest.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Item;
+
+use Magento\Checkout\Service\V1\Data\Cart\Item as Item;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutItemReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
+     */
+    public function testGetList()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_items', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $output = [];
+        foreach ($quote->getAllItems() as $item) {
+            $data = [
+                Item::ITEM_ID => $item->getId(),
+                Item::SKU => $item->getSku(),
+                Item::NAME => $item->getName(),
+                Item::PRICE => $item->getPrice(),
+                Item::QTY => $item->getQty(),
+                Item::PRODUCT_TYPE => $item->getProductType(),
+            ];
+
+            $output[] = $data;
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/items',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $this->assertEquals($output, $this->_webApiCall($serviceInfo, $requestData));
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..857475f87e8af2ca2d17960b31b7453dd9090c97
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/Item/WriteServiceTest.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\Item;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutItemWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     */
+    public function testAddItem()
+    {
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product')->load(2);
+        $productSku = $product->getSku();
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/items',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'AddItem',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "data" => [
+                "sku" => $productSku,
+                "qty" => 7,
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($quote->hasProductId(2));
+        $this->assertEquals(7, $quote->getItemByProduct($product)->getQty());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
+     */
+    public function testRemoveItem()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_items', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $productId = $product->getIdBySku('simple_one');
+        $product->load($productId);
+        $itemId = $quote->getItemByProduct($product)->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'RemoveItem',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "itemId" => $itemId,
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_items', 'reserved_order_id');
+        $this->assertFalse($quote->hasProductId($productId));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
+     */
+    public function testUpdateItem()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_items', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $productId = $product->getIdBySku('simple_one');
+        $product->load($productId);
+        $itemId = $quote->getItemByProduct($product)->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'UpdateItem',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "itemId" => $itemId,
+            "data" => [
+                "qty" => 5,
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_items', 'reserved_order_id');
+        $this->assertTrue($quote->hasProductId(1));
+        $this->assertEquals(5, $quote->getItemByProduct($product)->getQty());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..befd81cb2cdbeaac0196e06f594b559d051ef89b
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Checkout\Service\V1\PaymentMethod;
+
+use Magento\Checkout\Service\V1\Data\PaymentMethod;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutPaymentMethodReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testGetList()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getList',
+            ],
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $requestResponse = $this->_webApiCall($serviceInfo, $requestData);
+
+        $expectedResponse = [
+            PaymentMethod::CODE => 'checkmo',
+            PaymentMethod::TITLE => 'Check / Money order',
+        ];
+
+        $this->assertGreaterThan(0, count($requestResponse));
+        $this->assertContains($expectedResponse, $requestResponse);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_payment_saved.php
+     */
+    public function testGetPayment()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1_with_payment', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getPayment',
+            ],
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $requestResponse = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertArrayHasKey('method', $requestResponse);
+        $this->assertEquals('checkmo', $requestResponse['method']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd796eeb90da93200ee9638c21ff1c3d66445a09
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php
@@ -0,0 +1,211 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Checkout\Service\V1\PaymentMethod;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutPaymentMethodWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_payment_saved.php
+     */
+    public function testReSetPayment()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1_with_payment', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'set',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "method" => [
+                'method' => 'checkmo',
+                'po_number' => null,
+                'cc_owner' => 'John',
+                'cc_type' => null,
+                'cc_exp_year' => null,
+                'cc_exp_month' => null,
+            ],
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
+     */
+    public function testSetPaymentWithVirtualProduct()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_with_virtual_product', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'set',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "method" => [
+                'method' => 'checkmo',
+                'po_number' => '200',
+                'cc_owner' => 'tester',
+                'cc_type' => 'test',
+                'cc_exp_year' => '2014',
+                'cc_exp_month' => '1',
+            ],
+        ];
+        $this->assertNotNull($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testSetPaymentWithSimpleProduct()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'set',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "method" => [
+                'method' => 'checkmo',
+                'po_number' => '200',
+                'cc_owner' => 'tester',
+                'cc_type' => 'test',
+                'cc_exp_year' => '2014',
+                'cc_exp_month' => '1',
+            ],
+        ];
+
+        $this->assertNotNull($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Billing address is not set
+     */
+    public function testSetPaymentWithVirtualProductWithoutAddress()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_with_virtual_product_without_address', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'set',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "method" => [
+                'method' => 'checkmo',
+                'po_number' => '200',
+                'cc_owner' => 'tester',
+                'cc_type' => 'test',
+                'cc_exp_year' => '2014',
+                'cc_exp_month' => '1',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Shipping address is not set
+     */
+    public function testSetPaymentWithSimpleProductWithoutAddress()
+    {
+        /** @var \Magento\Sales\Model\Quote  $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_with_simple_product_without_address', 'reserved_order_id');
+        $cartId = $quote->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-payment-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'set',
+            ],
+        ];
+
+        $requestData = [
+            "cartId" => $cartId,
+            "method" => [
+                'method' => 'checkmo',
+                'po_number' => '200',
+                'cc_owner' => 'tester',
+                'cc_type' => 'test',
+                'cc_exp_year' => '2014',
+                'cc_exp_month' => '1',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1d95dea7a13d6036da233cdddff674a33360b57
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Checkout\Service\V1\ShippingMethod;
+
+use Magento\Checkout\Service\V1\Data\Cart\ShippingMethod;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'checkoutShippingMethodReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_shipping_method.php
+     */
+    public function testGetMethod()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+
+        $cartId = $quote->getId();
+
+        $shippingAddress = $quote->getShippingAddress();
+        list($carrierCode, $methodCode) = explode('_', $shippingAddress->getShippingMethod());
+        list($carrierTitle, $methodTitle) = explode(' - ', $shippingAddress->getShippingDescription());
+        $data = [
+            ShippingMethod::CARRIER_CODE => $carrierCode,
+            ShippingMethod::METHOD_CODE => $methodCode,
+            ShippingMethod::CARRIER_TITLE => $carrierTitle,
+            ShippingMethod::METHOD_TITLE => $methodTitle,
+            ShippingMethod::SHIPPING_AMOUNT => $shippingAddress->getShippingAmount(),
+            ShippingMethod::BASE_SHIPPING_AMOUNT => $shippingAddress->getBaseShippingAmount(),
+            ShippingMethod::AVAILABLE => true,
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $this->assertEquals($data, $this->_webApiCall($this->getSelectedMethodServiceInfo($cartId), $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
+     */
+    public function testGetMethodOfVirtualCart()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $cartId = $quote->load('test_order_with_virtual_product', 'reserved_order_id')->getId();
+
+        $result = $this->_webApiCall($this->getSelectedMethodServiceInfo($cartId), ["cartId" => $cartId]);
+        $this->assertEquals([], $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testGetMethodOfCartWithNoShippingMethod()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $cartId = $quote->load('test_order_1', 'reserved_order_id')->getId();
+
+        $result = $this->_webApiCall($this->getSelectedMethodServiceInfo($cartId), ["cartId" => $cartId]);
+        $this->assertEquals([], $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_and_address.php
+     *
+     */
+    public function testGetListForVirtualCart()
+    {
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $cartId = $quote->load('test_order_with_virtual_product', 'reserved_order_id')->getId();
+
+        $this->assertEquals([], $this->_webApiCall($this->getListServiceInfo($cartId), ["cartId" => $cartId]));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testGetList()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_1', 'reserved_order_id');
+        $cartId = $quote->getId();
+        if (!$cartId) {
+            $this->fail('quote fixture failed');
+        }
+        $quote->getShippingAddress()->collectShippingRates();
+        $expectedRates = $quote->getShippingAddress()->getGroupedAllShippingRates();
+
+        $expectedData = $this->convertRates($expectedRates, $quote->getQuoteCurrencyCode());
+
+        $requestData = ["cartId" => $cartId];
+
+        $returnedRates = $this->_webApiCall($this->getListServiceInfo($cartId), $requestData);
+        $this->assertEquals($expectedData, $returnedRates);
+    }
+
+    /**
+     * @param string $cartId
+     * @return array
+     */
+    protected function getSelectedMethodServiceInfo($cartId)
+    {
+        return $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/selected-shipping-method',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetMethod',
+            ],
+        ];
+    }
+
+    /**
+     * Service info
+     *
+     * @param int $cartId
+     * @return array
+     */
+    protected function getListServiceInfo($cartId)
+    {
+        return [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/shipping-methods',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+    }
+
+    /**
+     * Convert rate models array to data array
+     *
+     * @param string $currencyCode
+     * @param \Magento\Sales\Model\Quote\Address\Rate[] $groupedRates
+     * @return array
+     */
+    protected function convertRates($groupedRates, $currencyCode)
+    {
+        $result = [];
+        /** @var \Magento\Checkout\Service\V1\Data\Cart\ShippingMethodConverter $converter */
+        $converter = $this->objectManager->create('Magento\Checkout\Service\V1\Data\Cart\ShippingMethodConverter');
+        foreach ($groupedRates as $carrierRates) {
+            foreach ($carrierRates as $rate) {
+                $result[] = $converter->modelToDataObject($rate, $currencyCode)->__toArray();
+            }
+        }
+        return $result;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..95539b9aa22a6f6cfc348f1172822cff73c704f6
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Checkout/Service/V1/ShippingMethod/WriteServiceTest.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Checkout\Service\V1\ShippingMethod;
+
+use Magento\TestFramework\ObjectManager;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * @var \Magento\Sales\Model\Quote
+     */
+    protected $quote;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+    }
+
+    protected function getServiceInfo()
+    {
+        return [
+            'rest' => [
+                'resourcePath' => '/V1/carts/' . $this->quote->getId() . '/selected-shipping-method',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'checkoutShippingMethodWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutShippingMethodWriteServiceV1SetMethod',
+            ],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testSetMethod()
+    {
+        $this->quote->load('test_order_1', 'reserved_order_id');
+        $serviceInfo = $this->getServiceInfo();
+
+        $requestData = [
+            'cartId' => $this->quote->getId(),
+            'carrierCode' => 'flatrate',
+            'methodCode' => 'flatrate',
+        ];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(true, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
+     */
+    public function testSetMethodWrongMethod()
+    {
+        $this->quote->load('test_order_1', 'reserved_order_id');
+        $serviceInfo = $this->getServiceInfo();
+
+        $requestData = [
+            'cartId' => $this->quote->getId(),
+            'carrierCode' => 'flatrate',
+            'methodCode' => 'wrongMethod',
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\SoapFault $e) {
+            $message = $e->getMessage();
+        } catch (\Exception $e) {
+            $message = json_decode($e->getMessage())->message;
+        }
+        $this->assertEquals('Carrier with such method not found: flatrate, wrongMethod', $message);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
+     */
+    public function testSetMethodWithoutShippingAddress()
+    {
+        $this->quote->load('test_order_with_simple_product_without_address', 'reserved_order_id');
+        $serviceInfo = $this->getServiceInfo();
+
+        $requestData = [
+            'cartId' => $this->quote->getId(),
+            'carrierCode' => 'flatrate',
+            'methodCode' => 'flatrate',
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\SoapFault $e) {
+            $message = $e->getMessage();
+        } catch (\Exception $e) {
+            $message = json_decode($e->getMessage())->message;
+        }
+        $this->assertEquals('Shipping address is not set', $message);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/CheckoutAgreements/Service/V1/Agreement/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/CheckoutAgreements/Service/V1/Agreement/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..db6133696df0e1c5b26ffee84bba70c1a9f53504
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/CheckoutAgreements/Service/V1/Agreement/ReadServiceTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\CheckoutAgreements\Service\V1\Agreement;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    /**
+     * @var array
+     */
+    private $listServiceInfo;
+
+    protected function setUp()
+    {
+        $this->listServiceInfo = [
+            'soap' => [
+                'service' => 'checkoutAgreementsAgreementReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'checkoutAgreementsAgreementReadServiceV1GetList',
+            ],
+            'rest' => [
+                'resourcePath' => '/V1/carts/licence/',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+    }
+
+    /**
+     * Retrieve agreement by given name
+     *
+     * @param string $name
+     * @return \Magento\CheckoutAgreements\Model\Agreement
+     * @throws \InvalidArgumentException
+     */
+    protected function getAgreementByName($name)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var $agreement \Magento\CheckoutAgreements\Model\Agreement */
+        $agreement = $objectManager->create('Magento\CheckoutAgreements\Model\Agreement');
+        $agreement->load($name, 'name');
+        if (!$agreement->getId()) {
+            throw new \InvalidArgumentException('There is no checkout agreement with provided ID.');
+        }
+        return $agreement;
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php
+     * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php
+     */
+    public function testGetListReturnsEmptyListIfCheckoutAgreementsAreDisabledOnFrontend()
+    {
+        // Checkout agreements are disabled by default
+        $agreements = $this->_webApiCall($this->listServiceInfo, []);
+        $this->assertEmpty($agreements);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php
+     * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php
+     */
+    public function testGetListReturnsTheListOfActiveCheckoutAgreements()
+    {
+        // checkout/options/enable_agreements must be set to 1 in system configuration
+        // @todo remove next statement when \Magento\TestFramework\TestCase\WebapiAbstract::_updateAppConfig is fixed
+        $this->markTestIncomplete('This test relies on system configuration state.');
+        $agreementModel = $this->getAgreementByName('Checkout Agreement (active)');
+
+        $agreements = $this->_webApiCall($this->listServiceInfo, []);
+        $this->assertCount(1, $agreements);
+        $agreementData = $agreements[0];
+        $this->assertEquals($agreementModel->getId(), $agreementData['id']);
+        $this->assertEquals($agreementModel->getName(), $agreementData['name']);
+        $this->assertEquals($agreementModel->getContent(), $agreementData['content']);
+        $this->assertEquals($agreementModel->getContentHeight(), $agreementData['content_height']);
+        $this->assertEquals($agreementModel->getCheckboxText(), $agreementData['checkbox_text']);
+        $this->assertEquals($agreementModel->getIsActive(), $agreementData['active']);
+        $this->assertEquals($agreementModel->getIsHtml(), $agreementData['html']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ConfigurableProductManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ConfigurableProductManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..487580b00352b660e8be5962a2fbddfe552203b4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ConfigurableProductManagementTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\ConfigurableProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+use Magento\TestFramework\Helper\Bootstrap;
+
+class ConfigurableProductManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'configurableProductConfigurableProductManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/configurable-products/variation';
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php
+     */
+    public function testGetVariation()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GenerateVariation'
+            ]
+        ];
+        /** @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository */
+        $attributeRepository = Bootstrap::getObjectManager()->get(
+            'Magento\Catalog\Api\ProductAttributeRepositoryInterface'
+        );
+        $attribute = $attributeRepository->get('test_configurable');
+        $attributeOptionValue = $attribute->getOptions()[0]->getValue();
+        $data = [
+            'product' => [
+                'sku' => 'test',
+                'price' => 10.0
+            ],
+            'options' => [
+                [
+                    'attribute_id' => 'test_configurable',
+                    'values' => [
+                        [
+                            'value_index' => $attributeOptionValue,
+                            'pricing_value' => 100.0
+                        ]
+                    ]
+                ]
+            ]
+
+        ];
+        $actual = $this->_webApiCall($serviceInfo, $data);
+
+        $expectedItems = [
+            [
+                'sku' => 'test-',
+                'price' => 110.0,
+                'name' => '-',
+                'store_id' => 1,
+                'status' => 1,
+                'visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE,
+                'custom_attributes' => [
+                    [
+                        'attribute_code' => 'test_configurable',
+                        'value' => $attributeOptionValue
+                    ]
+                ]
+            ]
+        ];
+        ksort($expectedItems);
+        ksort($actual);
+        $this->assertEquals($expectedItems, $actual);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6c37af767e59e3017e0056be72fd05afebe7eda
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\ConfigurableProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config;
+
+class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'configurableProductLinkManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/configurable-products';
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testGetChildren()
+    {
+        $productSku = 'configurable';
+
+        /** @var array $result */
+        $result = $this->getChildren($productSku);
+        $this->assertCount(2, $result);
+
+        foreach ($result as $product) {
+            $this->assertArrayHasKey('custom_attributes', $product);
+            $this->assertArrayHasKey('price', $product);
+            $this->assertArrayHasKey('updated_at', $product);
+
+            $this->assertArrayHasKey('name', $product);
+            $this->assertContains('Configurable Option', $product['name']);
+
+            $this->assertArrayHasKey('sku', $product);
+            $this->assertContains('simple_', $product['sku']);
+
+            $this->assertArrayHasKey('status', $product);
+            $this->assertEquals('1', $product['status']);
+
+            $this->assertArrayHasKey('visibility', $product);
+            $this->assertEquals('1', $product['visibility']);
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/delete_association.php
+     */
+    public function testAddChild()
+    {
+        $productSku = 'configurable';
+        $childSku = 'simple_10';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/child',
+                'httpMethod' => Config::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'AddChild'
+            ]
+        ];
+        $res = $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'childSku' => $childSku]);
+        $this->assertTrue($res);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testRemoveChild()
+    {
+        $productSku = 'configurable';
+        $childSku = 'simple_10';
+        $this->assertTrue($this->removeChild($productSku, $childSku));
+    }
+
+    protected function removeChild($productSku, $childSku)
+    {
+        $resourcePath = self::RESOURCE_PATH . '/%s/child/%s';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => sprintf($resourcePath, $productSku, $childSku),
+                'httpMethod' => Config::HTTP_METHOD_DELETE
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'RemoveChild'
+            ]
+        ];
+        $requestData = ['productSku' => $productSku, 'childSku' => $childSku];
+        return $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    /**
+     * @param string $productSku
+     * @return string
+     */
+    protected function getChildren($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku  . '/children',
+                'httpMethod' => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetChildren'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..01f3bd7a1bddec8b358529b3ea79d86fa5134ee9
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionRepositoryTest.php
@@ -0,0 +1,289 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\ConfigurableProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config;
+
+class OptionRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'configurableProductOptionRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/configurable-products';
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testGet()
+    {
+        $productSku = 'configurable';
+
+        $options = $this->getList($productSku);
+        $this->assertTrue(is_array($options));
+        $this->assertNotEmpty($options);
+
+        foreach ($options as $option) {
+            /** @var array $result */
+            $result = $this->get($productSku, $option['id']);
+
+            $this->assertTrue(is_array($result));
+            $this->assertNotEmpty($result);
+
+            $this->assertArrayHasKey('id', $result);
+            $this->assertEquals($option['id'], $result['id']);
+
+            $this->assertArrayHasKey('attribute_id', $result);
+            $this->assertEquals($option['attribute_id'], $result['attribute_id']);
+
+            $this->assertArrayHasKey('label', $result);
+            $this->assertEquals($option['label'], $result['label']);
+
+            $this->assertArrayHasKey('values', $result);
+            $this->assertTrue(is_array($result['values']));
+            $this->assertEquals($option['values'], $result['values']);
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testGetList()
+    {
+        $productSku = 'configurable';
+
+        /** @var array $result */
+        $result = $this->getList($productSku);
+
+        $this->assertNotEmpty($result);
+        $this->assertTrue(is_array($result));
+        $this->assertArrayHasKey(0, $result);
+
+        $option = $result[0];
+
+        $this->assertNotEmpty($option);
+        $this->assertTrue(is_array($option));
+
+        $this->assertArrayHasKey('id', $option);
+        $this->assertArrayHasKey('label', $option);
+        $this->assertEquals($option['label'], 'Test Configurable');
+
+        $this->assertArrayHasKey('values', $option);
+        $this->assertTrue(is_array($option));
+        $this->assertNotEmpty($option);
+
+        $expectedValues = [
+            ['pricing_value' => 5, 'is_percent' => 0],
+            ['pricing_value' => 5, 'is_percent' => 0]
+        ];
+
+        $this->assertCount(count($expectedValues), $option['values']);
+
+        foreach ($option['values'] as $key => $value) {
+            $this->assertTrue(is_array($value));
+            $this->assertNotEmpty($value);
+
+            $this->assertArrayHasKey($key, $expectedValues);
+            $expectedValue = $expectedValues[$key];
+
+            $this->assertArrayHasKey('pricing_value', $value);
+            $this->assertEquals($expectedValue['pricing_value'], $value['pricing_value']);
+
+            $this->assertArrayHasKey('is_percent', $value);
+            $this->assertEquals($expectedValue['is_percent'], $value['is_percent']);
+        }
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testGetUndefinedProduct()
+    {
+        $productSku = 'product_not_exist';
+        $this->getList($productSku);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested option doesn't exist: -42
+     */
+    public function testGetUndefinedOption()
+    {
+        $productSku = 'configurable';
+        $attributeId = -42;
+        $this->get($productSku, $attributeId);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testDelete()
+    {
+        $productSku = 'configurable';
+
+        $optionList = $this->getList($productSku);
+        $optionId = $optionList[0]['id'];
+        $resultRemove = $this->delete($productSku, $optionId);
+        $optionListRemoved = $this->getList($productSku);
+
+        $this->assertTrue($resultRemove);
+        $this->assertEquals(count($optionList) - 1, count($optionListRemoved));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php
+     */
+    public function testAdd()
+    {
+        $productSku = 'simple';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options',
+                'httpMethod' => Config::HTTP_METHOD_POST
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save'
+            ]
+        ];
+        $option = [
+            'attribute_id' => 'test_configurable',
+            'type' => 'select',
+            'label' => 'Test',
+            'values' => [
+                [
+                    'value_index' => 1,
+                    'pricing_value' => '3',
+                    'is_percent' => 0
+                ]
+            ],
+        ];
+        /** @var int $result */
+        $result = $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'option' => $option]);
+        $this->assertGreaterThan(0, $result);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
+     */
+    public function testUpdate()
+    {
+        $productSku = 'configurable';
+        $configurableAttribute = $this->getConfigurableAttribute($productSku);
+        $optionId = $configurableAttribute[0]['id'];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options' . '/' . $optionId,
+                'httpMethod' => Config::HTTP_METHOD_PUT
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save'
+            ]
+        ];
+
+        $option = [
+            'label' => 'Update Test Configurable'
+        ];
+
+        $requestBody = ['option' => $option];
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $requestBody['productSku'] = $productSku;
+            $requestBody['option']['id'] = $optionId;
+        }
+
+        $result = $this->_webApiCall($serviceInfo, $requestBody);
+        $this->assertGreaterThan(0, $result);
+        $configurableAttribute = $this->getConfigurableAttribute($productSku);
+        $this->assertEquals($option['label'], $configurableAttribute[0]['label']);
+    }
+
+    /**
+     * @param string $productSku
+     * @return array
+     */
+    protected function getConfigurableAttribute($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options/all',
+                'httpMethod' => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+    }
+
+    /**
+     * @param string $productSku
+     * @param int $optionId
+     * @return bool
+     */
+    private function delete($productSku, $optionId)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options/' . $optionId,
+                'httpMethod' => Config::HTTP_METHOD_DELETE
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'optionId' => $optionId]);
+    }
+
+    /**
+     * @param $productSku
+     * @param $optionId
+     * @return array
+     */
+    protected function get($productSku, $optionId)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options/' . $optionId,
+                'httpMethod'   => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service'        => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation'      => self::SERVICE_NAME . 'Get'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'optionId' => $optionId]);
+    }
+
+    /**
+     * @param $productSku
+     * @return array
+     */
+    protected function getList($productSku)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/options/all',
+                'httpMethod'   => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service'        => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation'      => self::SERVICE_NAME . 'GetList'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo, ['productSku' => $productSku]);
+    }
+
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a99fd960dba16752a08df70f60cf05ca7d041e6
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OptionTypesListTest.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\ConfigurableProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config;
+
+class OptionTypesListTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_READ_NAME = 'configurableProductOptionTypesListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/configurable-products/:productSku/options/';
+
+    public function testGetTypes()
+    {
+        $expectedTypes = ['multiselect', 'select'];
+        $result = $this->getTypes();
+        $this->assertEquals($expectedTypes, $result);
+    }
+
+    /**
+     * @return array
+     */
+    protected function getTypes()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => str_replace(':productSku/', '', self::RESOURCE_PATH) . 'types',
+                'httpMethod'   => Config::HTTP_METHOD_GET
+            ],
+            'soap' => [
+                'service'        => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation'      => self::SERVICE_READ_NAME . 'GetItems'
+            ]
+        ];
+        return $this->_webApiCall($serviceInfo);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..32eca4e2256338056e569e6523e1f83c4dd3e31c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementMeTest.php
@@ -0,0 +1,335 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\CustomerInterface;
+use Magento\Customer\Model\CustomerRegistry;
+use Magento\Integration\Model\Oauth\Token as TokenModel;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Helper\Customer as CustomerHelper;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class AccountManagementMeTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @magentoApiDataFixture Magento/Customer/_files/customer.php
+ * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
+ */
+class AccountManagementMeTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/customers/me';
+    const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
+
+    /**
+     * @var CustomerRepositoryInterface
+     */
+    private $customerRepository;
+
+    /**
+     * @var AccountManagementInterface
+     */
+    private $customerAccountManagement;
+
+    /**
+     * @var CustomerRegistry
+     */
+    private $customerRegistry;
+
+    /**
+     * @var CustomerHelper
+     */
+    private $customerHelper;
+
+    /**
+     * @var TokenModel
+     */
+    private $token;
+
+    /**
+     * @var CustomerInterface
+     */
+    private $customerData;
+
+    /**
+     * @var \Magento\Framework\Reflection\DataObjectProcessor
+     */
+    private $dataObjectProcessor;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $this->_markTestAsRestOnly();
+
+        $this->customerRegistry = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Model\CustomerRegistry'
+        );
+
+        $this->customerRepository = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Api\CustomerRepositoryInterface',
+            ['customerRegistry' => $this->customerRegistry]
+        );
+
+        $this->customerAccountManagement = Bootstrap::getObjectManager()
+            ->get('Magento\Customer\Api\AccountManagementInterface');
+
+        $this->customerHelper = new CustomerHelper();
+        $this->customerData = $this->customerHelper->createSampleCustomer();
+
+        // get token
+        $this->resetTokenForCustomerSampleData();
+
+        $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Reflection\DataObjectProcessor'
+        );
+    }
+
+    /**
+     * Ensure that fixture customer and his addresses are deleted.
+     */
+    public function tearDown()
+    {
+        unset($this->customerRepository);
+
+        /** @var \Magento\Framework\Registry $registry */
+        $registry = Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', true);
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', false);
+        parent::tearDown();
+    }
+
+    public function testChangePassword()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/password',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+                'token' => $this->token,
+            ],
+        ];
+        $requestData = ['currentPassword' => 'test@123', 'newPassword' => '123@test'];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+
+        $customerResponseData = $this->customerAccountManagement
+            ->authenticate($this->customerData[CustomerInterface::EMAIL], '123@test');
+        $this->assertEquals($this->customerData[CustomerInterface::ID], $customerResponseData->getId());
+    }
+
+    public function testUpdateCustomer()
+    {
+        $customerData = $this->_getCustomerData($this->customerData[CustomerInterface::ID]);
+        $lastName = $customerData->getLastname();
+
+        $updatedCustomerData = $this->dataObjectProcessor->buildOutputDataArray(
+            $customerData,
+            'Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $updatedCustomerData[CustomerInterface::LASTNAME] = $lastName . 'Updated';
+        $updatedCustomerData[CustomerInterface::ID] = 25;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+                'token' => $this->token,
+            ],
+        ];
+        $requestData = ['customer' => $updatedCustomerData];
+
+        $response = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($lastName . "Updated", $response[CustomerInterface::LASTNAME]);
+
+        $customerData = $this->_getCustomerData($this->customerData[CustomerInterface::ID]);
+        $this->assertEquals($lastName . "Updated", $customerData->getLastname());
+    }
+
+    public function testGetCustomerData()
+    {
+        //Get expected details from the Service directly
+        $customerData = $this->_getCustomerData($this->customerData[CustomerInterface::ID]);
+        $expectedCustomerDetails = $this->dataObjectProcessor->buildOutputDataArray(
+            $customerData,
+            'Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $expectedCustomerDetails['addresses'][0]['id'] =
+            (int)$expectedCustomerDetails['addresses'][0]['id'];
+
+        $expectedCustomerDetails['addresses'][1]['id'] =
+            (int)$expectedCustomerDetails['addresses'][1]['id'];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+                'token' => $this->token,
+            ],
+        ];
+        $customerDetailsResponse = $this->_webApiCall($serviceInfo);
+
+        unset($expectedCustomerDetails['custom_attributes']);
+        unset($customerDetailsResponse['custom_attributes']); //for REST
+
+        $this->assertEquals($expectedCustomerDetails, $customerDetailsResponse);
+    }
+
+    public function testGetCustomerActivateCustomer()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/activate',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+                'token' => $this->token,
+            ],
+        ];
+        $requestData = ['confirmationKey' => $this->customerData[CustomerInterface::CONFIRMATION]];
+        $customerResponseData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($this->customerData[CustomerInterface::ID], $customerResponseData[CustomerInterface::ID]);
+        // Confirmation key is removed after confirmation
+        $this->assertFalse(isset($customerResponseData[CustomerInterface::CONFIRMATION]));
+    }
+
+    /**
+     * Return the customer details.
+     *
+     * @param int $customerId
+     * @return \Magento\Customer\Api\Data\CustomerInterface
+     */
+    protected function _getCustomerData($customerId)
+    {
+        $data = $this->customerRepository->getById($customerId);
+        $this->customerRegistry->remove($customerId);
+        return $data;
+    }
+
+    public function testGetDefaultBillingAddress()
+    {
+        $this->resetTokenForCustomerFixture();
+
+        $fixtureCustomerId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/customers/me/billingAddress",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+                'token' => $this->token,
+            ],
+        ];
+        $requestData = ['customerId' => $fixtureCustomerId];
+        $addressData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $this->getFirstFixtureAddressData(),
+            $addressData,
+            "Default billing address data is invalid."
+        );
+    }
+
+    public function testGetDefaultShippingAddress()
+    {
+        $this->resetTokenForCustomerFixture();
+
+        $fixtureCustomerId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/customers/me/shippingAddress",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+                'token' => $this->token,
+            ],
+        ];
+        $requestData = ['customerId' => $fixtureCustomerId];
+        $addressData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $this->getFirstFixtureAddressData(),
+            $addressData,
+            "Default shipping address data is invalid."
+        );
+    }
+
+    /**
+     * Retrieve data of the first fixture address.
+     *
+     * @return array
+     */
+    protected function getFirstFixtureAddressData()
+    {
+        return [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'city' => 'CityM',
+            'country_id' => 'US',
+            'company' => 'CompanyName',
+            'postcode' => '75477',
+            'telephone' => '3468676',
+            'street' => ['Green str, 67'],
+            'id' => 1,
+            'default_billing' => true,
+            'default_shipping' => true,
+            'customer_id' => '1',
+            'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
+        ];
+    }
+
+    /**
+     * Retrieve data of the second fixture address.
+     *
+     * @return array
+     */
+    protected function getSecondFixtureAddressData()
+    {
+        return [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'city' => 'CityX',
+            'country_id' => 'US',
+            'postcode' => '47676',
+            'telephone' => '3234676',
+            'street' => ['Black str, 48'],
+            'id' => 2,
+            'default_billing' => false,
+            'default_shipping' => false,
+            'customer_id' => '1',
+            'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
+        ];
+    }
+
+    /**
+     * Sets the test's access token for the customer fixture
+     */
+    protected function resetTokenForCustomerFixture()
+    {
+        $this->resetTokenForCustomer('customer@example.com', 'password');
+    }
+
+    /**
+     * Sets the test's access token for the created customer sample data
+     */
+    protected function resetTokenForCustomerSampleData()
+    {
+        $this->resetTokenForCustomer($this->customerData[CustomerInterface::EMAIL], 'test@123');
+    }
+
+    /**
+     * Sets the test's access token for a particular username and password.
+     *
+     * @param string $username
+     * @param string $password
+     */
+    protected function resetTokenForCustomer($username, $password)
+    {
+        // get customer ID token
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+        $requestData = ['username' => $username, 'password' => $password];
+        $this->token = $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..50a2790634cf7a5ec4d45a3b6d885f7fb8d35fcd
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php
@@ -0,0 +1,778 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\CustomerInterface as Customer;
+use Magento\Customer\Model\AccountManagement;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Helper\Customer as CustomerHelper;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Test class for Magento\Customer\Api\AccountManagementInterface
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class AccountManagementTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'customerAccountManagementV1';
+    const RESOURCE_PATH = '/V1/customers';
+
+    /**
+     * Sample values for testing
+     */
+    const ATTRIBUTE_CODE = 'attribute_code';
+    const ATTRIBUTE_VALUE = 'attribute_value';
+
+    /**
+     * @var AccountManagementInterface
+     */
+    private $accountManagement;
+
+    /**
+     * @var \Magento\Customer\Api\Data\AddressDataBuilder
+     */
+    private $addressBuilder;
+
+    /**
+     * @var \Magento\Customer\Api\Data\CustomerDataBuilder
+     */
+    private $customerBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\SortOrderBuilder
+     */
+    private $sortOrderBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\Search\FilterGroupBuilder
+     */
+    private $filterGroupBuilder;
+
+    /**
+     * @var CustomerHelper
+     */
+    private $customerHelper;
+
+    /**
+     * @var array
+     */
+    private $currentCustomerId;
+
+    /**
+     * @var \Magento\Framework\Reflection\DataObjectProcessor
+     */
+    private $dataObjectProcessor;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $this->accountManagement = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Api\AccountManagementInterface'
+        );
+        $this->addressBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\AddressDataBuilder'
+        );
+        $this->customerBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\CustomerDataBuilder'
+        );
+        $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->sortOrderBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SortOrderBuilder'
+        );
+        $this->filterGroupBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\Search\FilterGroupBuilder'
+        );
+        $this->customerHelper = new CustomerHelper();
+
+        $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Reflection\DataObjectProcessor'
+        );
+    }
+
+    public function tearDown()
+    {
+        if (!empty($this->currentCustomerId)) {
+            foreach ($this->currentCustomerId as $customerId) {
+                $serviceInfo = [
+                    'rest' => [
+                        'resourcePath' => self::RESOURCE_PATH . '/' . $customerId,
+                        'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+                    ],
+                    'soap' => [
+                        'service' => CustomerRepositoryTest::SERVICE_NAME,
+                        'serviceVersion' => self::SERVICE_VERSION,
+                        'operation' => CustomerRepositoryTest::SERVICE_NAME . 'DeleteById',
+                    ],
+                ];
+
+                $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
+
+                $this->assertTrue($response);
+            }
+        }
+        unset($this->accountManagement);
+    }
+
+    public function testCreateCustomer()
+    {
+        $customerData = $this->_createCustomer();
+        $this->assertNotNull($customerData['id']);
+    }
+
+    public function testCreateCustomerWithErrors()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST, ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'CreateAccount',
+            ],
+        ];
+
+        $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
+            $this->customerHelper->createSampleCustomerDataObject(),
+            '\Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $invalidEmail = 'invalid';
+        $customerDataArray['email'] = $invalidEmail;
+        $requestData = ['customer' => $customerDataArray, 'password' => CustomerHelper::PASSWORD];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception did not occur.');
+        } catch (\Exception $e) {
+            if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+                $expectedException = new InputException();
+                $expectedException->addError(
+                    InputException::INVALID_FIELD_VALUE,
+                    ['fieldName' => 'email', 'value' => $invalidEmail]
+                );
+                $this->assertInstanceOf('SoapFault', $e);
+                $this->checkSoapFault(
+                    $e,
+                    $expectedException->getRawMessage(),
+                    'env:Sender',
+                    $expectedException->getParameters() // expected error parameters
+                );
+            } else {
+                $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+                $exceptionData = $this->processRestExceptionResult($e);
+                $expectedExceptionData = [
+                    'message' => InputException::INVALID_FIELD_VALUE,
+                    'parameters' => [
+                        'fieldName' => 'email',
+                        'value' => $invalidEmail,
+                    ],
+                ];
+                $this->assertEquals($expectedExceptionData, $exceptionData);
+            }
+        }
+    }
+
+    /**
+     * Test customer activation when it is required
+     *
+     * @magentoConfigFixture default_store customer/create_account/confirm 0
+     */
+    public function testActivateCustomer()
+    {
+        $customerData = $this->_createCustomer();
+        $this->assertNotNull($customerData[Customer::CONFIRMATION], 'Customer activation is not required');
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::EMAIL] . '/activate',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Activate',
+            ],
+        ];
+
+        $requestData = [
+            'email' => $customerData[Customer::EMAIL],
+            'confirmationKey' => $customerData[Customer::CONFIRMATION],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals($customerData[Customer::ID], $result[Customer::ID], 'Wrong customer!');
+        $this->assertTrue(
+            !isset($result[Customer::CONFIRMATION]) || $result[Customer::CONFIRMATION] === null,
+            'Customer is not activated!'
+        );
+    }
+
+    public function testGetCustomerActivateCustomer()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::EMAIL] . '/activate',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Activate',
+            ],
+        ];
+        $requestData = [
+            'email' => $customerData[Customer::EMAIL],
+            'confirmationKey' => $customerData[Customer::CONFIRMATION],
+        ];
+
+        $customerResponseData = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals($customerData[Customer::ID], $customerResponseData[Customer::ID]);
+        // Confirmation key is removed after confirmation
+        $this->assertFalse(isset($customerResponseData[Customer::CONFIRMATION]));
+    }
+
+    public function testValidateResetPasswordLinkToken()
+    {
+        $customerData = $this->_createCustomer();
+        /** @var \Magento\Customer\Model\Customer $customerModel */
+        $customerModel = Bootstrap::getObjectManager()->create('Magento\Customer\Model\CustomerFactory')
+            ->create();
+        $customerModel->load($customerData[Customer::ID]);
+        $rpToken = 'lsdj579slkj5987slkj595lkj';
+        $customerModel->setRpToken('lsdj579slkj5987slkj595lkj');
+        $customerModel->setRpTokenCreatedAt(date('Y-m-d'));
+        $customerModel->save();
+        $path = self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/password/resetLinkToken/' . $rpToken;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $path,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'ValidateResetPasswordLinkToken',
+            ],
+        ];
+
+        $this->_webApiCall(
+            $serviceInfo,
+            ['customerId' => $customerData['id'], 'resetPasswordLinkToken' => $rpToken]
+        );
+    }
+
+    public function testValidateResetPasswordLinkTokenInvalidToken()
+    {
+        $customerData = $this->_createCustomer();
+        $invalidToken = 'fjjkafjie';
+        $path = self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/password/resetLinkToken/' . $invalidToken;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $path,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'ValidateResetPasswordLinkToken',
+            ],
+        ];
+
+        $expectedMessage = 'Reset password token mismatch.';
+
+        try {
+            if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+                $this->_webApiCall(
+                    $serviceInfo,
+                    ['customerId' => $customerData['id'], 'resetPasswordLinkToken' => 'invalid']
+                );
+            } else {
+                $this->_webApiCall($serviceInfo);
+            }
+            $this->fail("Expected exception to be thrown.");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception message does not match"
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        }
+    }
+
+    public function testInitiatePasswordMissingRequiredFields()
+    {
+        $this->_markTestAsRestOnly('Soap clients explicitly check for required fields based on WSDL.');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/password',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ]
+        ];
+
+        try {
+            $this->_webApiCall($serviceInfo);
+        } catch (\Exception $e) {
+            $this->assertEquals(\Magento\Webapi\Exception::HTTP_BAD_REQUEST, $e->getCode());
+            $exceptionData = $this->processRestExceptionResult($e);
+            $expectedExceptionData = [
+                'message' => InputException::DEFAULT_MESSAGE,
+                'errors' => [
+                    [
+                        'message' => InputException::REQUIRED_FIELD,
+                        'parameters' => [
+                            'fieldName' => 'email',
+                        ],
+                    ],
+                    [
+                        'message' => InputException::REQUIRED_FIELD,
+                        'parameters' => [
+                            'fieldName' => 'template',
+                        ]
+                    ],
+                ],
+            ];
+            $this->assertEquals($expectedExceptionData, $exceptionData);
+        }
+    }
+
+    public function testInitiatePasswordReset()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/password',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'InitiatePasswordReset',
+            ],
+        ];
+        $requestData = [
+            'email' => $customerData[Customer::EMAIL],
+            'template' => AccountManagement::EMAIL_RESET,
+            'websiteId' => $customerData[Customer::WEBSITE_ID],
+        ];
+        // This api doesn't return any response.
+        // No exception or response means the request was processed successfully.
+        // The webapi framework does not return the header information as yet. A check for HTTP 200 would be ideal here
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    public function testSendPasswordResetLinkBadEmailOrWebsite()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/password',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'InitiatePasswordReset',
+            ],
+        ];
+        $requestData = [
+            'email' => 'dummy@example.com',
+            'template' => AccountManagement::EMAIL_RESET,
+            'websiteId' => 0,
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $expectedErrorParameters =
+                [
+                    'fieldName' => 'email',
+                    'fieldValue' => 'dummy@example.com',
+                    'field2Name' => 'websiteId',
+                    'field2Value' => 0,
+                ];
+            if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+                $errorObj = $this->processRestExceptionResult($e);
+                $this->assertEquals(
+                    NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+                    $errorObj['message']
+                );
+                $this->assertEquals($expectedErrorParameters, $errorObj['parameters']);
+                $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+            } else {
+                $this->assertInstanceOf('SoapFault', $e);
+                $this->checkSoapFault(
+                    $e,
+                    NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+                    'env:Sender',
+                    $expectedErrorParameters
+                );
+            }
+        }
+    }
+
+    public function testGetConfirmationStatus()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/confirm',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetConfirmationStatus',
+            ],
+        ];
+
+        $confirmationResponse = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
+
+        $this->assertEquals(AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED, $confirmationResponse);
+    }
+
+    public function testResendConfirmation()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/confirm',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'ResendConfirmation',
+            ],
+        ];
+        $requestData = [
+            'email' => $customerData[Customer::EMAIL],
+            'websiteId' => $customerData[Customer::WEBSITE_ID],
+        ];
+        // This api doesn't return any response.
+        // No exception or response means the request was processed successfully.
+        // The webapi framework does not return the header information as yet. A check for HTTP 200 would be ideal here
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+
+    public function testResendConfirmationBadEmailOrWebsite()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/confirm',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'ResendConfirmation',
+            ],
+        ];
+        $requestData = [
+            'email' => 'dummy@example.com',
+            'websiteId' => 0,
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $expectedErrorParameters =
+                [
+                    'fieldName' => 'email',
+                    'fieldValue' => 'dummy@example.com',
+                    'field2Name' => 'websiteId',
+                    'field2Value' => 0,
+                ];
+            if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+                $errorObj = $this->processRestExceptionResult($e);
+                $this->assertEquals(
+                    NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+                    $errorObj['message']
+                );
+                $this->assertEquals($expectedErrorParameters, $errorObj['parameters']);
+                $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+            } else {
+                $this->assertInstanceOf('SoapFault', $e);
+                $this->checkSoapFault(
+                    $e,
+                    NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+                    'env:Sender',
+                    $expectedErrorParameters
+                );
+            }
+        }
+    }
+
+    public function testValidateCustomerData()
+    {
+        $customerData = $this->customerHelper->createSampleCustomerDataObject();
+        $customerData = $this->customerBuilder->populate($customerData)
+            ->setFirstname(null)->setLastname(null)->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/validate',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Validate',
+            ],
+        ];
+        $customerData = $this->dataObjectProcessor->buildOutputDataArray(
+            $customerData,
+            '\Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $requestData = ['customer' => $customerData];
+        $validationResponse = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertFalse($validationResponse['valid']);
+        $this->assertEquals('The first name cannot be empty.', $validationResponse['messages'][0]);
+        $this->assertEquals('The last name cannot be empty.', $validationResponse['messages'][1]);
+    }
+
+    public function testIsReadonly()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/permissions/readonly',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'IsReadonly',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
+
+        $this->assertFalse($response);
+    }
+
+    public function testEmailAvailable()
+    {
+        $customerData = $this->_createCustomer();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/isEmailAvailable',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'IsEmailAvailable',
+            ],
+        ];
+        $requestData = [
+            'customerEmail' => $customerData[Customer::EMAIL],
+            'websiteId' => $customerData[Customer::WEBSITE_ID],
+        ];
+        $this->assertFalse($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    public function testEmailAvailableInvalidEmail()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/isEmailAvailable',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'IsEmailAvailable',
+            ],
+        ];
+        $requestData = [
+            'customerEmail' => 'invalid',
+            'websiteId' => 0,
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/attribute_user_defined_address.php
+     * @magentoApiDataFixture Magento/Customer/_files/attribute_user_defined_customer.php
+     */
+    public function testCustomAttributes()
+    {
+        //Sample customer data comes with the disable_auto_group_change custom attribute
+        $customerData = $this->customerHelper->createSampleCustomerDataObject();
+        //address attribute code from fixture
+        $fixtureAddressAttributeCode = 'address_user_attribute';
+        //customer attribute code from fixture
+        $fixtureCustomerAttributeCode = 'user_attribute';
+        //Custom Attribute Values
+        $address1CustomAttributeValue = 'value1';
+        $address2CustomAttributeValue = 'value2';
+        $customerCustomAttributeValue = 'value3';
+
+        $addresses = $customerData->getAddresses();
+        $address1 = $this->addressBuilder
+            ->populate($addresses[0])
+            ->setCustomAttribute($fixtureAddressAttributeCode, $address1CustomAttributeValue)
+            ->create();
+        $address2 = $this->addressBuilder
+            ->populate($addresses[1])
+            ->setCustomAttribute($fixtureAddressAttributeCode, $address2CustomAttributeValue)
+            ->create();
+
+        $customer = $this->customerBuilder
+            ->populate($customerData)
+            ->setAddresses([$address1, $address2])
+            ->setCustomAttribute($fixtureCustomerAttributeCode, $customerCustomAttributeValue)
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'CreateAccount',
+            ],
+        ];
+
+        $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
+            $customer,
+            '\Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $requestData = ['customer' => $customerDataArray, 'password' => CustomerHelper::PASSWORD];
+        $customerData = $this->_webApiCall($serviceInfo, $requestData);
+        $customerId = $customerData['id'];
+        //TODO: Fix assertions to verify custom attributes
+        $this->assertNotNull($customerData);
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerId ,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => CustomerRepositoryTest::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => CustomerRepositoryTest::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
+        $this->assertTrue($response);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
+     */
+    public function testGetDefaultBillingAddress()
+    {
+        $fixtureCustomerId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$fixtureCustomerId/billingAddress",
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetDefaultBillingAddress',
+            ],
+        ];
+        $requestData = ['customerId' => $fixtureCustomerId];
+        $addressData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $this->getFirstFixtureAddressData(),
+            $addressData,
+            "Default billing address data is invalid."
+        );
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
+     */
+    public function testGetDefaultShippingAddress()
+    {
+        $fixtureCustomerId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$fixtureCustomerId/shippingAddress",
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetDefaultShippingAddress',
+            ],
+        ];
+        $requestData = ['customerId' => $fixtureCustomerId];
+        $addressData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $this->getFirstFixtureAddressData(),
+            $addressData,
+            "Default shipping address data is invalid."
+        );
+    }
+
+    /**
+     * @return array|bool|float|int|string
+     */
+    protected function _createCustomer()
+    {
+        $customerData = $this->customerHelper->createSampleCustomer();
+        $this->currentCustomerId[] = $customerData['id'];
+        return $customerData;
+    }
+
+    /**
+     * Retrieve data of the first fixture address.
+     *
+     * @return array
+     */
+    protected function getFirstFixtureAddressData()
+    {
+        return [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'city' => 'CityM',
+            'country_id' => 'US',
+            'company' => 'CompanyName',
+            'postcode' => '75477',
+            'telephone' => '3468676',
+            'street' => ['Green str, 67'],
+            'id' => 1,
+            'default_billing' => true,
+            'default_shipping' => true,
+            'customer_id' => '1',
+            'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3acea94fc9bff6081ddd8f0647fc6e3f17020a7
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php
@@ -0,0 +1,274 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\AddressInterface as Address;
+use Magento\Customer\Model\Data\AttributeMetadata;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * Class AddressMetadataTest
+ */
+class AddressMetadataTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "customerAddressMetadataV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/attributeMetadata/customerAddress";
+
+    /**
+     * Test retrieval of attribute metadata for the address entity type.
+     *
+     * @param string $attributeCode The attribute code of the requested metadata.
+     * @param array $expectedMetadata Expected entity metadata for the attribute code.
+     * @dataProvider getAttributeMetadataDataProvider
+     */
+    public function testGetAttributeMetadata($attributeCode, $expectedMetadata)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/attribute/$attributeCode",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAttributeMetadata',
+            ],
+        ];
+
+        $requestData = [
+            'attributeCode' => $attributeCode,
+        ];
+
+        $attributeMetadata = $this->_webapiCall($serviceInfo, $requestData);
+        $validationResult = $this->checkValidationRules($expectedMetadata, $attributeMetadata);
+        list($expectedMetadata, $attributeMetadata) = $validationResult;
+        $this->assertEquals($expectedMetadata, $attributeMetadata);
+    }
+
+    /**
+     * Data provider for testGetAttributeMetadata.
+     *
+     * @return array
+     */
+    public function getAttributeMetadataDataProvider()
+    {
+        return [
+            Address::POSTCODE => [
+                Address::POSTCODE,
+                [
+                    AttributeMetadata::ATTRIBUTE_CODE => 'postcode',
+                    AttributeMetadata::FRONTEND_INPUT => 'text',
+                    AttributeMetadata::INPUT_FILTER => '',
+                    AttributeMetadata::STORE_LABEL => 'Zip/Postal Code',
+                    AttributeMetadata::VALIDATION_RULES => [],
+                    AttributeMetadata::VISIBLE => true,
+                    AttributeMetadata::REQUIRED => false,
+                    AttributeMetadata::MULTILINE_COUNT => 0,
+                    AttributeMetadata::DATA_MODEL => 'Magento\Customer\Model\Attribute\Data\Postcode',
+                    AttributeMetadata::OPTIONS => [],
+                    AttributeMetadata::FRONTEND_CLASS => '',
+                    AttributeMetadata::FRONTEND_LABEL => 'Zip/Postal Code',
+                    AttributeMetadata::NOTE => '',
+                    AttributeMetadata::SYSTEM => true,
+                    AttributeMetadata::USER_DEFINED => false,
+                    AttributeMetadata::BACKEND_TYPE => 'varchar',
+                    AttributeMetadata::SORT_ORDER => 110
+                ],
+            ]
+        ];
+    }
+
+    /**
+     * Test retrieval of all address attribute metadata.
+     */
+    public function testGetAllAttributesMetadata()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAllAttributesMetadata',
+            ],
+        ];
+
+        $attributeMetadata = $this->_webApiCall($serviceInfo);
+        $this->assertCount(19, $attributeMetadata);
+        $postcode = $this->getAttributeMetadataDataProvider()[Address::POSTCODE][1];
+        $validationResult = $this->checkMultipleAttributesValidationRules($postcode, $attributeMetadata);
+        list($postcode, $attributeMetadata) = $validationResult;
+        $this->assertContains($postcode, $attributeMetadata);
+    }
+
+    /**
+     * Test retrieval of custom address attribute metadata.
+     *
+     * @magentoApiDataFixture Magento/Customer/_files/attribute_user_defined_address_custom_attribute.php
+     */
+    public function testGetCustomAttributesMetadata()
+    {
+        $customAttributeCode = 'custom_attribute1';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/custom',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetCustomAttributesMetadata',
+            ],
+        ];
+
+        $requestData = ['attribute_code' => $customAttributeCode];
+        $attributeMetadata = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertCount(2, $attributeMetadata);
+        $this->assertEquals($customAttributeCode, $attributeMetadata[0]['attribute_code']);
+    }
+
+    /**
+     * Test retrieval of attributes
+     *
+     * @param string $formCode Form code
+     * @param array $expectedMetadata The expected attribute metadata
+     * @dataProvider getAttributesDataProvider
+     */
+    public function testGetAttributes($formCode, $expectedMetadata)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/form/$formCode",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAttributes',
+            ],
+        ];
+
+        $requestData = [
+            'formCode' => $formCode,
+        ];
+
+        $attributeMetadataList = $this->_webApiCall($serviceInfo, $requestData);
+        foreach ($attributeMetadataList as $attributeMetadata) {
+            if (isset($attributeMetadata['attribute_code'])
+                && $attributeMetadata['attribute_code'] == $expectedMetadata['attribute_code']
+            ) {
+                $validationResult = $this->checkValidationRules($expectedMetadata, $attributeMetadata);
+                list($expectedMetadata, $attributeMetadata) = $validationResult;
+                $this->assertEquals($expectedMetadata, $attributeMetadata);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Data provider for testGetAttributes.
+     *
+     * @return array
+     */
+    public function getAttributesDataProvider()
+    {
+        $attributeMetadata = $this->getAttributeMetadataDataProvider();
+        return [
+            [
+                'customer_address_edit',
+                $attributeMetadata[Address::POSTCODE][1],
+            ]
+        ];
+    }
+
+    /**
+     * Checks that expected and actual attribute metadata validation rules are equal
+     * and removes the validation rules entry from expected and actual attribute metadata
+     *
+     * @param array $expectedResult
+     * @param array $actualResult
+     * @return array
+     */
+    public function checkValidationRules($expectedResult, $actualResult)
+    {
+        $expectedRules = [];
+        $actualRules = [];
+
+        if (isset($expectedResult[AttributeMetadata::VALIDATION_RULES])) {
+            $expectedRules = $expectedResult[AttributeMetadata::VALIDATION_RULES];
+            unset($expectedResult[AttributeMetadata::VALIDATION_RULES]);
+        }
+        if (isset($actualResult[AttributeMetadata::VALIDATION_RULES])) {
+            $actualRules = $actualResult[AttributeMetadata::VALIDATION_RULES];
+            unset($actualResult[AttributeMetadata::VALIDATION_RULES]);
+        }
+
+        if (is_array($expectedRules) && is_array($actualRules)) {
+            foreach ($expectedRules as $expectedRule) {
+                if (isset($expectedRule['name']) && isset($expectedRule['value'])) {
+                    $found = false;
+                    foreach ($actualRules as $actualRule) {
+                        if (isset($actualRule['name']) && isset($actualRule['value'])) {
+                            if ($expectedRule['name'] == $actualRule['name']
+                                && $expectedRule['value'] == $actualRule['value']
+                            ) {
+                                $found = true;
+                                break;
+                            }
+                        }
+                    }
+                    $this->assertTrue($found);
+                }
+            }
+        }
+        return [$expectedResult, $actualResult];
+    }
+
+    /**
+     * Check specific attribute validation rules in set of multiple attributes
+     *
+     * @param array $expectedResult Set of expected attribute metadata
+     * @param array $actualResultSet Set of actual attribute metadata
+     * @return array
+     */
+    public function checkMultipleAttributesValidationRules($expectedResult, $actualResultSet)
+    {
+        if (is_array($expectedResult) && is_array($actualResultSet)) {
+            if (isset($expectedResult[AttributeMetadata::ATTRIBUTE_CODE])) {
+                foreach ($actualResultSet as $actualAttributeKey => $actualAttribute) {
+                    if (isset($actualAttribute[AttributeMetadata::ATTRIBUTE_CODE])
+                        && $expectedResult[AttributeMetadata::ATTRIBUTE_CODE]
+                        == $actualAttribute[AttributeMetadata::ATTRIBUTE_CODE]
+                    ) {
+                        $this->checkValidationRules($expectedResult, $actualAttribute);
+                        unset($actualResultSet[$actualAttributeKey][AttributeMetadata::VALIDATION_RULES]);
+                    }
+                }
+                unset($expectedResult[AttributeMetadata::VALIDATION_RULES]);
+            }
+        }
+        return [$expectedResult, $actualResultSet];
+    }
+
+    /**
+     * Remove test attribute
+     */
+    public static function tearDownAfterClass()
+    {
+        parent::tearDownAfterClass();
+        /** @var \Magento\Customer\Model\Attribute $attribute */
+        $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Model\Attribute'
+        );
+        foreach (['custom_attribute1', 'custom_attribute2'] as $attributeCode) {
+            $attribute->loadByCode('customer_address', $attributeCode);
+            $attribute->delete();
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bc344be7173a39a1ddc571cdc56189029e56a6e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressRepositoryTest.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+class AddressRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SOAP_SERVICE_NAME = 'customerAddressRepositoryV1';
+    const SOAP_SERVICE_VERSION = 'V1';
+
+    /** @var \Magento\Customer\Api\AddressRepositoryInterface */
+    protected $addressRepository;
+
+    /** @var \Magento\Customer\Api\CustomerRepositoryInterface */
+    protected $customerRepository;
+
+    protected function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->customerRepository = $objectManager->get(
+            'Magento\Customer\Api\CustomerRepositoryInterface'
+        );
+        $this->addressRepository = $objectManager->get(
+            'Magento\Customer\Api\AddressRepositoryInterface'
+        );
+        parent::setUp();
+    }
+
+    /**
+     * Ensure that fixture customer and his addresses are deleted.
+     */
+    protected function tearDown()
+    {
+        /** @var \Magento\Framework\Registry $registry */
+        $registry = Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', true);
+
+        try {
+            $fixtureFirstAddressId = 1;
+            $this->addressRepository->deleteById($fixtureFirstAddressId);
+        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            /** First address fixture was not used */
+        }
+        try {
+            $fixtureSecondAddressId = 2;
+            $this->addressRepository->deleteById($fixtureSecondAddressId);
+        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            /** Second address fixture was not used */
+        }
+        try {
+            $fixtureCustomerId = 1;
+            $this->customerRepository->deleteById($fixtureCustomerId);
+        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            /** Customer fixture was not used */
+        }
+
+        $registry->unregister('isSecureArea');
+        $registry->register('isSecureArea', false);
+        parent::tearDown();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer_address.php
+     */
+    public function testGetAddress()
+    {
+        $fixtureAddressId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/customers/addresses/{$fixtureAddressId}",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SOAP_SERVICE_NAME,
+                'serviceVersion' => self::SOAP_SERVICE_VERSION,
+                'operation' => self::SOAP_SERVICE_NAME . 'GetById',
+            ],
+        ];
+        $requestData = ['addressId' => $fixtureAddressId];
+        $addressData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $this->getFirstFixtureAddressData(),
+            $addressData,
+            "Address data is invalid."
+        );
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     * @magentoApiDataFixture Magento/Customer/_files/customer_address.php
+     */
+    public function testDeleteAddress()
+    {
+        $fixtureAddressId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/V1/addresses/{$fixtureAddressId}",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SOAP_SERVICE_NAME,
+                'serviceVersion' => self::SOAP_SERVICE_VERSION,
+                'operation' => self::SOAP_SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        $requestData = ['addressId' => $fixtureAddressId];
+        $response = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($response, 'Expected response should be true.');
+
+        $this->setExpectedException('Magento\Framework\Exception\NoSuchEntityException', 'No such entity with addressId = 1');
+        $this->addressRepository->getById($fixtureAddressId);
+    }
+
+    /**
+     * Retrieve data of the first fixture address.
+     *
+     * @return array
+     */
+    protected function getFirstFixtureAddressData()
+    {
+        return [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'city' => 'CityM',
+            'country_id' => 'US',
+            'company' => 'CompanyName',
+            'postcode' => '75477',
+            'telephone' => '3468676',
+            'street' => ['Green str, 67'],
+            'id' => 1,
+            'default_billing' => true,
+            'default_shipping' => true,
+            'customer_id' => '1',
+            'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
+        ];
+    }
+
+    /**
+     * Retrieve data of the second fixture address.
+     *
+     * @return array
+     */
+    protected function getSecondFixtureAddressData()
+    {
+        return [
+            'firstname' => 'John',
+            'lastname' => 'Smith',
+            'city' => 'CityX',
+            'country_id' => 'US',
+            'postcode' => '47676',
+            'telephone' => '3234676',
+            'street' => ['Black str, 48'],
+            'id' => 2,
+            'default_billing' => false,
+            'default_shipping' => false,
+            'customer_id' => '1',
+            'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bba031a61ccd5a60271279e14809de94ab72d468
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerMetadataTest.php
@@ -0,0 +1,321 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\CustomerInterface as Customer;
+use Magento\Customer\Model\Data\AttributeMetadata;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * Class CustomerMetadataTest
+ */
+class CustomerMetadataTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "customerCustomerMetadataV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/attributeMetadata/customer";
+
+    /**
+     * Test retrieval of attribute metadata for the customer entity type.
+     *
+     * @param string $attributeCode The attribute code of the requested metadata.
+     * @param array $expectedMetadata Expected entity metadata for the attribute code.
+     * @dataProvider getAttributeMetadataDataProvider
+     */
+    public function testGetAttributeMetadata($attributeCode, $expectedMetadata)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/attribute/$attributeCode",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAttributeMetadata',
+            ],
+        ];
+
+        $requestData = [
+            'attributeCode' => $attributeCode,
+        ];
+
+        $attributeMetadata = $this->_webapiCall($serviceInfo, $requestData);
+
+        $validationResult = $this->checkValidationRules($expectedMetadata, $attributeMetadata);
+        list($expectedMetadata, $attributeMetadata) = $validationResult;
+        $this->assertEquals($expectedMetadata, $attributeMetadata);
+    }
+
+    /**
+     * Data provider for testGetAttributeMetadata.
+     *
+     * @return array
+     */
+    public function getAttributeMetadataDataProvider()
+    {
+        return [
+            Customer::FIRSTNAME => [
+                Customer::FIRSTNAME,
+                [
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'firstname',
+                    AttributeMetadata::FRONTEND_INPUT   => 'text',
+                    AttributeMetadata::INPUT_FILTER     => '',
+                    AttributeMetadata::STORE_LABEL      => 'First Name',
+                    AttributeMetadata::VALIDATION_RULES => [
+                        ['name' => 'min_text_length', 'value' => 1],
+                        ['name' => 'max_text_length', 'value' => 255],
+                    ],
+                    AttributeMetadata::VISIBLE          => true,
+                    AttributeMetadata::REQUIRED         => true,
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
+                    AttributeMetadata::DATA_MODEL       => '',
+                    AttributeMetadata::OPTIONS          => [],
+                    AttributeMetadata::FRONTEND_CLASS   => ' required-entry',
+                    AttributeMetadata::FRONTEND_LABEL   => 'First Name',
+                    AttributeMetadata::NOTE             => '',
+                    AttributeMetadata::SYSTEM           => true,
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::BACKEND_TYPE     => 'varchar',
+                    AttributeMetadata::SORT_ORDER       => 40
+                ],
+            ],
+            Customer::GENDER => [
+                Customer::GENDER,
+                [
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'gender',
+                    AttributeMetadata::FRONTEND_INPUT   => 'select',
+                    AttributeMetadata::INPUT_FILTER     => '',
+                    AttributeMetadata::STORE_LABEL      => 'Gender',
+                    AttributeMetadata::VALIDATION_RULES => [],
+                    AttributeMetadata::VISIBLE          => false,
+                    AttributeMetadata::REQUIRED         => false,
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
+                    AttributeMetadata::DATA_MODEL       => '',
+                    AttributeMetadata::OPTIONS          => [
+                        ['label' => '', 'value' => ''],
+                        ['label' => 'Male', 'value' => '1'],
+                        ['label' => 'Female', 'value' => '2'],
+                    ],
+                    AttributeMetadata::FRONTEND_CLASS   => '',
+                    AttributeMetadata::FRONTEND_LABEL   => 'Gender',
+                    AttributeMetadata::NOTE             => '',
+                    AttributeMetadata::SYSTEM           => false,
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::BACKEND_TYPE     => 'int',
+                    AttributeMetadata::SORT_ORDER       => 110
+                ],
+            ],
+            Customer::WEBSITE_ID => [
+                Customer::WEBSITE_ID,
+                [
+                    AttributeMetadata::ATTRIBUTE_CODE   => 'website_id',
+                    AttributeMetadata::FRONTEND_INPUT   => 'select',
+                    AttributeMetadata::INPUT_FILTER     => '',
+                    AttributeMetadata::STORE_LABEL      => 'Associate to Website',
+                    AttributeMetadata::VALIDATION_RULES => [],
+                    AttributeMetadata::VISIBLE          => true,
+                    AttributeMetadata::REQUIRED         => true,
+                    AttributeMetadata::MULTILINE_COUNT  => 0,
+                    AttributeMetadata::DATA_MODEL       => '',
+                    AttributeMetadata::OPTIONS          => [
+                        ['label' => 'Admin', 'value' => '0'],
+                        ['label' => 'Main Website', 'value' => '1'],
+                    ],
+                    AttributeMetadata::FRONTEND_CLASS   => ' required-entry',
+                    AttributeMetadata::FRONTEND_LABEL   => 'Associate to Website',
+                    AttributeMetadata::NOTE             => '',
+                    AttributeMetadata::SYSTEM           => true,
+                    AttributeMetadata::USER_DEFINED     => false,
+                    AttributeMetadata::BACKEND_TYPE     => 'static',
+                    AttributeMetadata::SORT_ORDER       => 10
+                ],
+            ]
+        ];
+    }
+
+    /**
+     * Test retrieval of all customer attribute metadata.
+     */
+    public function testGetAllAttributesMetadata()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAllAttributesMetadata',
+            ],
+        ];
+
+        $attributeMetadata = $this->_webApiCall($serviceInfo);
+
+        $this->assertCount(23, $attributeMetadata);
+
+        $firstName = $this->getAttributeMetadataDataProvider()[Customer::FIRSTNAME][1];
+        $validationResult = $this->checkMultipleAttributesValidationRules($firstName, $attributeMetadata);
+        list($firstName, $attributeMetadata) = $validationResult;
+        $this->assertContains($firstName, $attributeMetadata);
+
+        $websiteId = $this->getAttributeMetadataDataProvider()[Customer::WEBSITE_ID][1];
+        $validationResult = $this->checkMultipleAttributesValidationRules($websiteId, $attributeMetadata);
+        list($websiteId, $attributeMetadata) = $validationResult;
+        $this->assertContains($websiteId, $attributeMetadata);
+    }
+
+    /**
+     * Test retrieval of custom customer attribute metadata.
+     */
+    public function testGetCustomAttributesMetadata()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/custom',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetCustomAttributesMetadata',
+            ],
+        ];
+
+        $attributeMetadata = $this->_webApiCall($serviceInfo);
+
+        //Default custom attribute code 'disable_auto_group_change'
+        $this->assertCount(1, $attributeMetadata);
+        $this->assertEquals('disable_auto_group_change', $attributeMetadata[0]['attribute_code']);
+    }
+
+    /**
+     * Test retrieval of attributes
+     *
+     * @param string $formCode Form code
+     * @param array $expectedMetadata The expected attribute metadata
+     * @dataProvider getAttributesDataProvider
+     */
+    public function testGetAttributes($formCode, $expectedMetadata)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/form/$formCode",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetAttributes',
+            ],
+        ];
+
+        $requestData = [
+            'formCode' => $formCode,
+        ];
+
+        $attributeMetadataList = $this->_webApiCall($serviceInfo, $requestData);
+        foreach ($attributeMetadataList as $attributeMetadata) {
+            if (isset($attributeMetadata['attribute_code'])
+                && $attributeMetadata['attribute_code'] == $expectedMetadata['attribute_code']) {
+                $validationResult = $this->checkValidationRules($expectedMetadata, $attributeMetadata);
+                list($expectedMetadata, $attributeMetadata) = $validationResult;
+                $this->assertEquals($expectedMetadata, $attributeMetadata);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Data provider for testGetAttributes.
+     *
+     * @return array
+     */
+    public function getAttributesDataProvider()
+    {
+        $attributeMetadata = $this->getAttributeMetadataDataProvider();
+        return [
+            [
+                'adminhtml_customer',
+                $attributeMetadata[Customer::FIRSTNAME][1],
+            ],
+            [
+                'adminhtml_customer',
+                $attributeMetadata[Customer::GENDER][1]
+            ]
+        ];
+    }
+
+    /**
+     * Checks that expected and actual attribute metadata validation rules are equal
+     * and removes the validation rules entry from expected and actual attribute metadata
+     *
+     * @param array $expectedResult
+     * @param array $actualResult
+     * @return array
+     */
+    public function checkValidationRules($expectedResult, $actualResult)
+    {
+        $expectedRules = [];
+        $actualRules   = [];
+
+        if (isset($expectedResult[AttributeMetadata::VALIDATION_RULES])) {
+            $expectedRules = $expectedResult[AttributeMetadata::VALIDATION_RULES];
+            unset($expectedResult[AttributeMetadata::VALIDATION_RULES]);
+        }
+        if (isset($actualResult[AttributeMetadata::VALIDATION_RULES])) {
+            $actualRules = $actualResult[AttributeMetadata::VALIDATION_RULES];
+            unset($actualResult[AttributeMetadata::VALIDATION_RULES]);
+        }
+
+        if (is_array($expectedRules) && is_array($actualRules)) {
+            foreach ($expectedRules as $expectedRule) {
+                if (isset($expectedRule['name']) && isset($expectedRule['value'])) {
+                    $found = false;
+                    foreach ($actualRules as $actualRule) {
+                        if (isset($actualRule['name']) && isset($actualRule['value'])) {
+                            if ($expectedRule['name'] == $actualRule['name']
+                                && $expectedRule['value'] == $actualRule['value']
+                            ) {
+                                $found = true;
+                                break;
+                            }
+                        }
+                    }
+                    $this->assertTrue($found);
+                }
+            }
+        }
+        return [$expectedResult, $actualResult];
+    }
+
+    /**
+     * Check specific attribute validation rules in set of multiple attributes
+     *
+     * @param array $expectedResult Set of expected attribute metadata
+     * @param array $actualResultSet Set of actual attribute metadata
+     * @return array
+     */
+    public function checkMultipleAttributesValidationRules($expectedResult, $actualResultSet)
+    {
+        if (is_array($expectedResult) && is_array($actualResultSet)) {
+            if (isset($expectedResult[AttributeMetadata::ATTRIBUTE_CODE])) {
+                foreach ($actualResultSet as $actualAttributeKey => $actualAttribute) {
+                    if (isset($actualAttribute[AttributeMetadata::ATTRIBUTE_CODE])
+                        && $expectedResult[AttributeMetadata::ATTRIBUTE_CODE]
+                        == $actualAttribute[AttributeMetadata::ATTRIBUTE_CODE]
+                    ) {
+                        $this->checkValidationRules($expectedResult, $actualAttribute);
+                        unset($actualResultSet[$actualAttributeKey][AttributeMetadata::VALIDATION_RULES]);
+                    }
+                }
+                unset($expectedResult[AttributeMetadata::VALIDATION_RULES]);
+            }
+        }
+        return [$expectedResult, $actualResultSet];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..db1b03f1f4772c921d98cb043c5d2d63dc6fd41a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
@@ -0,0 +1,659 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Api\Data\CustomerInterface as Customer;
+use Magento\Framework\Api\SearchCriteria;
+use Magento\Framework\Exception\InputException;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Helper\Customer as CustomerHelper;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Test class for Magento\Customer\Api\CustomerRepositoryInterface
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class CustomerRepositoryTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'customerCustomerRepositoryV1';
+    const RESOURCE_PATH = '/V1/customers';
+
+    /**
+     * Sample values for testing
+     */
+    const ATTRIBUTE_CODE = 'attribute_code';
+    const ATTRIBUTE_VALUE = 'attribute_value';
+
+    /**
+     * @var CustomerRepositoryInterface
+     */
+    private $customerRepository;
+
+    /**
+     * @var \Magento\Customer\Api\Data\AddressDataBuilder
+     */
+    private $addressBuilder;
+
+    /**
+     * @var \Magento\Customer\Api\Data\CustomerDataBuilder
+     */
+    private $customerBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\SortOrderBuilder
+     */
+    private $sortOrderBuilder;
+
+    /**
+     * @var \Magento\Framework\Api\Search\FilterGroupBuilder
+     */
+    private $filterGroupBuilder;
+
+    /**
+     * @var \Magento\Customer\Model\CustomerRegistry
+     */
+    private $customerRegistry;
+
+    /**
+     * @var CustomerHelper
+     */
+    private $customerHelper;
+
+    /**
+     * @var array
+     */
+    private $currentCustomerId;
+
+    /**
+     * @var \Magento\Framework\Reflection\DataObjectProcessor
+     */
+    private $dataObjectProcessor;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $this->customerRegistry = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Model\CustomerRegistry'
+        );
+
+        $this->customerRepository = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Api\CustomerRepositoryInterface',
+            ['customerRegistry' => $this->customerRegistry]
+        );
+        $this->addressBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\AddressDataBuilder'
+        );
+        $this->customerBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Customer\Api\Data\CustomerDataBuilder'
+        );
+        $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->sortOrderBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SortOrderBuilder'
+        );
+        $this->filterGroupBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\Search\FilterGroupBuilder'
+        );
+        $this->customerHelper = new CustomerHelper();
+
+        $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Reflection\DataObjectProcessor'
+        );
+    }
+
+    public function tearDown()
+    {
+        if (!empty($this->currentCustomerId)) {
+            foreach ($this->currentCustomerId as $customerId) {
+                $serviceInfo = [
+                    'rest' => [
+                        'resourcePath' => self::RESOURCE_PATH . '/' . $customerId,
+                        'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+                    ],
+                    'soap' => [
+                        'service' => self::SERVICE_NAME,
+                        'serviceVersion' => self::SERVICE_VERSION,
+                        'operation' => self::SERVICE_NAME . 'DeleteById',
+                    ],
+                ];
+
+                $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
+
+                $this->assertTrue($response);
+            }
+        }
+        unset($this->customerRepository);
+    }
+
+    public function testDeleteCustomer()
+    {
+        $customerData = $this->_createCustomer();
+        $this->currentCustomerId = [];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID],
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
+        } else {
+            $response = $this->_webApiCall($serviceInfo);
+        }
+
+        $this->assertTrue($response);
+
+        //Verify if the customer is deleted
+        $this->setExpectedException(
+            'Magento\Framework\Exception\NoSuchEntityException',
+            sprintf("No such entity with customerId = %s", $customerData[Customer::ID])
+        );
+        $this->_getCustomerData($customerData[Customer::ID]);
+    }
+
+    public function testDeleteCustomerInvalidCustomerId()
+    {
+        $invalidId = -1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $invalidId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+
+        $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+        try {
+            $this->_webApiCall($serviceInfo, ['customerId' => $invalidId]);
+
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => $invalidId], $errorObj['parameters']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    public function testUpdateCustomer()
+    {
+        $customerData = $this->_createCustomer();
+        $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
+        $lastName = $existingCustomerDataObject->getLastname();
+        $customerData[Customer::LASTNAME] = $lastName . 'Updated';
+        $newCustomerDataObject = $this->customerBuilder->populateWithArray($customerData)->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
+            $newCustomerDataObject,
+            'Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $requestData = ['customer' => $newCustomerDataObject];
+        $response = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue(!is_null($response));
+
+        //Verify if the customer is updated
+        $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
+        $this->assertEquals($lastName . "Updated", $existingCustomerDataObject->getLastname());
+    }
+
+    /**
+     * Verify expected behavior when the website id is not set
+     */
+    public function testUpdateCustomerNoWebsiteId()
+    {
+        $customerData = $this->customerHelper->createSampleCustomer();
+        $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
+        $lastName = $existingCustomerDataObject->getLastname();
+        $customerData[Customer::LASTNAME] = $lastName . 'Updated';
+        $newCustomerDataObject = $this->customerBuilder->populateWithArray($customerData)->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
+            $newCustomerDataObject,
+            'Magento\Customer\Api\Data\CustomerInterface'
+        );
+        unset($newCustomerDataObject['website_id']);
+        $requestData = ['customer' => $newCustomerDataObject];
+
+        $expectedMessage = '"Associate to Website" is a required value.';
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception.");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj =  $this->customerHelper->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message'], 'Invalid message: "' . $e->getMessage() . '"');
+            $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        }
+    }
+
+    public function testUpdateCustomerException()
+    {
+        $customerData = $this->_createCustomer();
+        $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
+        $lastName = $existingCustomerDataObject->getLastname();
+
+        //Set non-existent id = -1
+        $customerData[Customer::LASTNAME] = $lastName . 'Updated';
+        $customerData[Customer::ID] = -1;
+
+        $newCustomerDataObject = $this->customerBuilder->populateWithArray($customerData)->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/-1",
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
+            $newCustomerDataObject,
+            'Magento\Customer\Api\Data\CustomerInterface'
+        );
+        $requestData = ['customer' => $newCustomerDataObject];
+
+        $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception.");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => -1], $errorObj['parameters']);
+            $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    /**
+     * Test with a single filter
+     */
+    public function testSearchCustomers()
+    {
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData = $this->_createCustomer();
+        $filter = $builder
+            ->setField(Customer::EMAIL)
+            ->setValue($customerData[Customer::EMAIL])
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getList',
+            ],
+        ];
+        $searchData = $this->dataObjectProcessor->buildOutputDataArray(
+            $this->searchCriteriaBuilder->create(),
+            'Magento\Framework\Api\SearchCriteriaInterface'
+        );
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]);
+    }
+
+    /**
+     * Test with a single filter using GET
+     */
+    public function testSearchCustomersUsingGET()
+    {
+        $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData = $this->_createCustomer();
+        $filter = $builder
+            ->setField(Customer::EMAIL)
+            ->setValue($customerData[Customer::EMAIL])
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchQueryString = http_build_query($requestData);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        $searchResults = $this->_webApiCall($serviceInfo);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]);
+    }
+
+    /**
+     * Test with empty GET based filter
+     */
+    public function testSearchCustomersUsingGETEmptyFilter()
+    {
+        $this->_markTestAsRestOnly('Soap clients explicitly check for required fields based on WSDL.');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo);
+        } catch (\Exception $e) {
+            $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+            $exceptionData = $this->processRestExceptionResult($e);
+            $expectedExceptionData = [
+                'message' => InputException::REQUIRED_FIELD,
+                'parameters' => [
+                    'fieldName' => 'searchCriteria'
+                ],
+            ];
+            $this->assertEquals($expectedExceptionData, $exceptionData);
+        }
+    }
+
+    /**
+     * Test using multiple filters
+     */
+    public function testSearchCustomersMultipleFiltersWithSort()
+    {
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData1 = $this->_createCustomer();
+        $customerData2 = $this->_createCustomer();
+        $filter1 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData1[Customer::EMAIL])
+            ->create();
+        $filter2 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData2[Customer::EMAIL])
+            ->create();
+        $filter3 = $builder->setField(Customer::LASTNAME)
+            ->setValue($customerData1[Customer::LASTNAME])
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter1, $filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3]);
+
+        /**@var \Magento\Framework\Api\SortOrderBuilder $sortOrderBuilder */
+        $sortOrderBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SortOrderBuilder'
+        );
+        /** @var \Magento\Framework\Api\SortOrder $sortOrder */
+        $sortOrder = $sortOrderBuilder->setField(Customer::EMAIL)->setDirection(SearchCriteria::SORT_ASC)->create();
+        $this->searchCriteriaBuilder->setSortOrders([$sortOrder]);
+
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getList',
+            ],
+        ];
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(2, $searchResults['total_count']);
+        $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
+        $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]);
+    }
+
+    /**
+     * Test using multiple filters using GET
+     */
+    public function testSearchCustomersMultipleFiltersWithSortUsingGET()
+    {
+        $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData1 = $this->_createCustomer();
+        $customerData2 = $this->_createCustomer();
+        $filter1 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData1[Customer::EMAIL])
+            ->create();
+        $filter2 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData2[Customer::EMAIL])
+            ->create();
+        $filter3 = $builder->setField(Customer::LASTNAME)
+            ->setValue($customerData1[Customer::LASTNAME])
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter1, $filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3]);
+        $this->searchCriteriaBuilder->setSortOrders([Customer::EMAIL => SearchCriteria::SORT_ASC]);
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchQueryString = http_build_query($requestData);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        $searchResults = $this->_webApiCall($serviceInfo);
+        $this->assertEquals(2, $searchResults['total_count']);
+        $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
+        $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]);
+    }
+
+    /**
+     * Test and verify multiple filters using And-ed non-existent filter value
+     */
+    public function testSearchCustomersNonExistentMultipleFilters()
+    {
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData1 = $this->_createCustomer();
+        $customerData2 = $this->_createCustomer();
+        $filter1 = $filter1 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData1[Customer::EMAIL])
+            ->create();
+        $filter2 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData2[Customer::EMAIL])
+            ->create();
+        $filter3 = $builder->setField(Customer::LASTNAME)
+            ->setValue('INVALID')
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter1, $filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3]);
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getList',
+            ],
+        ];
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.');
+    }
+
+    /**
+     * Test and verify multiple filters using And-ed non-existent filter value using GET
+     */
+    public function testSearchCustomersNonExistentMultipleFiltersGET()
+    {
+        $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $customerData1 = $this->_createCustomer();
+        $customerData2 = $this->_createCustomer();
+        $filter1 = $filter1 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData1[Customer::EMAIL])
+            ->create();
+        $filter2 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData2[Customer::EMAIL])
+            ->create();
+        $filter3 = $builder->setField(Customer::LASTNAME)
+            ->setValue('INVALID')
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter1, $filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3]);
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchQueryString = http_build_query($requestData);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.');
+    }
+
+    /**
+     * Test using multiple filters
+     */
+    public function testSearchCustomersMultipleFilterGroups()
+    {
+        $customerData1 = $this->_createCustomer();
+
+        /** @var \Magento\Framework\Api\FilterBuilder $builder */
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $filter1 = $builder->setField(Customer::EMAIL)
+            ->setValue($customerData1[Customer::EMAIL])
+            ->create();
+        $filter2 = $builder->setField(Customer::MIDDLENAME)
+            ->setValue($customerData1[Customer::MIDDLENAME])
+            ->create();
+        $filter3 = $builder->setField(Customer::MIDDLENAME)
+            ->setValue('invalid')
+            ->create();
+        $filter4 = $builder->setField(Customer::LASTNAME)
+            ->setValue($customerData1[Customer::LASTNAME])
+            ->create();
+
+        $this->searchCriteriaBuilder->addFilter([$filter1]);
+        $this->searchCriteriaBuilder->addFilter([$filter2, $filter3]);
+        $this->searchCriteriaBuilder->addFilter([$filter4]);
+        $searchCriteria = $this->searchCriteriaBuilder->setCurrentPage(1)->setPageSize(10)->create();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getList',
+            ],
+        ];
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
+
+        // Add an invalid And-ed data with multiple groups to yield no result
+        $filter4 = $builder->setField(Customer::LASTNAME)
+            ->setValue('invalid')
+            ->create();
+
+        $this->searchCriteriaBuilder->addFilter([$filter1]);
+        $this->searchCriteriaBuilder->addFilter([$filter2, $filter3]);
+        $this->searchCriteriaBuilder->addFilter([$filter4]);
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(0, $searchResults['total_count']);
+    }
+
+    /**
+     * Retrieve customer data by Id
+     *
+     * @param int $customerId
+     * @return \Magento\Customer\Api\Data\CustomerInterface
+     */
+    protected function _getCustomerData($customerId)
+    {
+        $customerData =  $this->customerRepository->getById($customerId);
+        $this->customerRegistry->remove($customerId);
+        return $customerData;
+    }
+
+    /**
+     * @return array|bool|float|int|string
+     */
+    protected function _createCustomer()
+    {
+        $customerData = $this->customerHelper->createSampleCustomer();
+        $this->currentCustomerId[] = $customerData['id'];
+        return $customerData;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..70c6294ebb972258359846a461128d8e34822830
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupManagementTest.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Model\Data\Group as CustomerGroup;
+use Magento\Customer\Model\GroupRegistry;
+use Magento\Customer\Model\Resource\GroupRepository;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * Class GroupManagementTest
+ */
+class GroupManagementTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "customerGroupManagementV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/customerGroups";
+
+    /**
+     * @var GroupRegistry
+     */
+    private $groupRegistry;
+
+    /**
+     * @var GroupRepository
+     */
+    private $groupRepository;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->groupRegistry = $objectManager->get('Magento\Customer\Model\GroupRegistry');
+        $this->groupRepository = $objectManager->get('Magento\Customer\Model\Resource\GroupRepository');
+    }
+
+    /**
+     * Verify the retrieval of the default group for storeId equal to 1.
+     *
+     * @param int $storeId The store Id
+     * @param array $defaultGroupData The default group data for the store with the specified Id.
+     *
+     * @dataProvider getDefaultGroupDataProvider
+     */
+    public function testGetDefaultGroup($storeId, $defaultGroupData)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/default/$storeId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupManagementV1GetDefaultGroup',
+            ],
+        ];
+        $requestData = ['storeId' => $storeId];
+        $groupData = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals($defaultGroupData, $groupData, "The default group does not match.");
+    }
+
+    /**
+     * The testGetDefaultGroup data provider.
+     *
+     * @return array
+     */
+    public function getDefaultGroupDataProvider()
+    {
+        return [
+            'admin' => [
+                0,
+                [
+                    CustomerGroup::ID => 1,
+                    CustomerGroup::CODE => 'General',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer'
+                ],
+            ],
+            'base' => [
+                1,
+                [
+                    CustomerGroup::ID => 1,
+                    CustomerGroup::CODE => 'General',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer'
+                ],
+            ]
+        ];
+    }
+
+    /**
+     * Verify the retrieval of a non-existent storeId will return an expected fault.
+     */
+    public function testGetDefaultGroupNonExistentStore()
+    {
+        /* Store id should not exist */
+        $nonExistentStoreId = 9876;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/default/$nonExistentStoreId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupManagementV1GetDefaultGroup',
+            ],
+        ];
+        $requestData = ['storeId' => $nonExistentStoreId];
+        $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+            $this->assertContains((string)$nonExistentStoreId, $e->getMessage());
+        }
+    }
+
+    /**
+     * Verify that the group with the specified Id can or cannot be deleted.
+     *
+     * @param int $groupId The group Id
+     * @param bool $isDeleteable Whether the group can or cannot be deleted.
+     *
+     * @dataProvider isReadonlyDataProvider
+     */
+    public function testIsReadonly($groupId, $isDeleteable)
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId/permissions",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupManagementV1IsReadonly',
+            ],
+        ];
+
+        $requestData = [CustomerGroup::ID => $groupId];
+
+        $isReadonly = $this->_webApiCall($serviceInfo, $requestData);
+
+        $failureMessage = $isDeleteable
+            ? 'The group should be deleteable.' : 'The group should not be deleteable.';
+        $this->assertEquals($isDeleteable, !$isReadonly, $failureMessage);
+    }
+
+    /**
+     * The testIsReadonly data provider.
+     *
+     * @return array
+     */
+    public function isReadonlyDataProvider()
+    {
+        return [
+            'NOT LOGGED IN' => [0, false],
+            'General' => [1, false],
+            'Wholesale' => [2, true],
+            'Retailer' => [3, true]
+        ];
+    }
+
+    /**
+     * Verify that the group with the specified Id can or cannot be deleted.
+     */
+    public function testIsReadonlyNoSuchGroup()
+    {
+        /* This group ID should not exist in the store. */
+        $groupId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId/permissions",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupManagementV1IsReadonly',
+            ],
+        ];
+
+        $requestData = [CustomerGroup::ID => $groupId];
+
+        $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception.");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+            $this->assertContains((string)$groupId, $e->getMessage());
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..862349c1cbe539b7bee28b8a844457e4c6e153c2
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php
@@ -0,0 +1,1007 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Customer\Api;
+
+use Magento\Customer\Model\Data\Group as CustomerGroup;
+use Magento\Customer\Model\GroupRegistry;
+use Magento\Customer\Model\Resource\GroupRepository;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+/**
+ * Class GroupRepositoryTest
+ */
+class GroupRepositoryTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "customerGroupRepositoryV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/customerGroups";
+
+    /**
+     * @var GroupRegistry
+     */
+    private $groupRegistry;
+
+    /**
+     * @var GroupRepository
+     */
+    private $groupRepository;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->groupRegistry = $objectManager->get('Magento\Customer\Model\GroupRegistry');
+        $this->groupRepository = $objectManager->get('Magento\Customer\Model\Resource\GroupRepository');
+    }
+
+    /**
+     * Execute per test cleanup.
+     */
+    public function tearDown()
+    {
+    }
+
+    /**
+     * Cleaning up the extra groups that might have been created as part of the testing.
+     */
+    public static function tearDownAfterClass()
+    {
+    }
+
+    /**
+     * Verify the retrieval of a customer group by Id.
+     *
+     * @param array $testGroup The group data for the group being retrieved.
+     *
+     * @dataProvider getGroupDataProvider
+     */
+    public function testGetGroupById($testGroup)
+    {
+        $groupId = $testGroup[CustomerGroup::ID];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1GetById',
+            ],
+        ];
+        $requestData = [CustomerGroup::ID => $groupId];
+        $groupData = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals($testGroup, $groupData, "The group data does not match.");
+    }
+
+    /**
+     * The testGetGroup data provider.
+     *
+     * @return array
+     */
+    public function getGroupDataProvider()
+    {
+        return [
+            'NOT LOGGED IN' => [
+                [
+                    CustomerGroup::ID => 0,
+                    CustomerGroup::CODE => 'NOT LOGGED IN',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer',
+                ],
+            ],
+            'General' => [
+                [
+                    CustomerGroup::ID => 1,
+                    CustomerGroup::CODE => 'General',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer',
+                ],
+            ],
+            'Wholesale' => [
+                [
+                    CustomerGroup::ID => 2,
+                    CustomerGroup::CODE => 'Wholesale',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer',
+                ],
+            ],
+            'Retailer' => [
+                [
+                    CustomerGroup::ID => 3,
+                    CustomerGroup::CODE => 'Retailer',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                    CustomerGroup::TAX_CLASS_NAME => 'Retail Customer',
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * Verify that creating a new group works via REST.
+     */
+    public function testCreateGroupRest()
+    {
+        $this->_markTestAsRestOnly();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Create Group REST',
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $groupId = $this->_webApiCall($serviceInfo, $requestData)[CustomerGroup::ID];
+        $this->assertNotNull($groupId);
+
+        $newGroup = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupId, $newGroup->getId(), 'The group id does not match.');
+        $this->assertEquals($groupData[CustomerGroup::CODE], $newGroup->getCode(), 'The group code does not match.');
+        $this->assertEquals(
+            $groupData[CustomerGroup::TAX_CLASS_ID],
+            $newGroup->getTaxClassId(),
+            'The group tax class id does not match.'
+        );
+    }
+
+    /**
+     * Verify that creating a new group with a duplicate group name fails with an error via REST.
+     */
+    public function testCreateGroupDuplicateGroupRest()
+    {
+        $builder = Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\GroupDataBuilder');
+        $this->_markTestAsRestOnly();
+
+        $duplicateGroupCode = 'Duplicate Group Code REST';
+
+        $this->createGroup(
+            $builder->populateWithArray([
+                CustomerGroup::ID => null,
+                CustomerGroup::CODE => $duplicateGroupCode,
+                CustomerGroup::TAX_CLASS_ID => 3,
+            ])->create()
+        );
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => $duplicateGroupCode,
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\Exception $e) {
+            $errorData = json_decode($e->getMessage(), true);
+
+            $this->assertEquals(
+                'Customer Group already exists.',
+                $errorData['message']
+            );
+            $this->assertEquals(400, $e->getCode(), 'Invalid HTTP code');
+        }
+    }
+
+    /**
+     * Verify that creating a new group works via REST if tax class id is empty, defaults 3.
+     */
+    public function testCreateGroupDefaultTaxClassIdRest()
+    {
+        $this->_markTestAsRestOnly();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Default Class Tax ID REST',
+            CustomerGroup::TAX_CLASS_ID => null,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $groupId = $this->_webApiCall($serviceInfo, $requestData)[CustomerGroup::ID];
+        $this->assertNotNull($groupId);
+
+        $newGroup = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupId, $newGroup->getId(), 'The group id does not match.');
+        $this->assertEquals($groupData[CustomerGroup::CODE], $newGroup->getCode(), 'The group code does not match.');
+        $this->assertEquals(
+            GroupRepository::DEFAULT_TAX_CLASS_ID,
+            $newGroup->getTaxClassId(),
+            'The group tax class id does not match.'
+        );
+    }
+
+    /**
+     * Verify that creating a new group without a code fails with an error.
+     */
+    public function testCreateGroupNoCodeExpectExceptionRest()
+    {
+        $this->_markTestAsRestOnly();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => null,
+            CustomerGroup::TAX_CLASS_ID => null,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\Exception $e) {
+            // @codingStandardsIgnoreStart
+            $this->assertContains(
+                '{"message":"%fieldName is a required field.","parameters":{"fieldName":"code"}',
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+            // @codingStandardsIgnoreEnd
+        }
+    }
+
+    /**
+     * Verify that creating a new group with an invalid tax class id fails with an error.
+     */
+    public function testCreateGroupInvalidTaxClassIdRest()
+    {
+        $this->_markTestAsRestOnly();
+
+        $invalidTaxClassId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Invalid Tax Class Id Code',
+            CustomerGroup::TAX_CLASS_ID => $invalidTaxClassId,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\Exception $e) {
+            // @codingStandardsIgnoreStart
+            $this->assertContains(
+                '{"message":"Invalid value of \"%value\" provided for the %fieldName field.","parameters":{"fieldName":"taxClassId","value":9999}',
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+            // codingStandardsIgnoreEnd
+        }
+    }
+
+    /**
+     * Verify that an attempt to update via POST is not allowed.
+     */
+    public function testCreateGroupWithIdRest()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => 88,
+            CustomerGroup::CODE => 'Create Group With Id REST',
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception');
+        } catch (\Exception $e) {
+            $this->assertContains(
+                '{"message":"No such entity with %fieldName = %fieldValue","parameters":{"fieldName":"id","fieldValue":88}',
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that creating a new group fails via SOAP if there is an Id specified.
+     */
+    public function testCreateGroupWithIdSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => 88,
+            CustomerGroup::CODE => 'Create Group with Id SOAP',
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                'No such entity with %fieldName = %fieldValue',
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that updating an existing group works via REST.
+     */
+    public function testUpdateGroupRest()
+    {
+        $this->_markTestAsRestOnly();
+        $builder = Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\GroupDataBuilder');
+        $groupId = $this->createGroup(
+            $builder->populateWithArray([
+                CustomerGroup::ID => null,
+                CustomerGroup::CODE => 'New Group REST',
+                CustomerGroup::TAX_CLASS_ID => 3,
+            ])->create()
+        );
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => $groupId,
+            CustomerGroup::CODE => 'Updated Group REST',
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $this->assertEquals($groupId, $this->_webApiCall($serviceInfo, $requestData)[CustomerGroup::ID]);
+
+        $group = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupData[CustomerGroup::CODE], $group->getCode(), 'The group code did not change.');
+        $this->assertEquals(
+            $groupData[CustomerGroup::TAX_CLASS_ID],
+            $group->getTaxClassId(),
+            'The group tax class id did not change'
+        );
+    }
+
+    /**
+     * Verify that updating a non-existing group throws an exception.
+     */
+    public function testUpdateGroupNotExistingGroupRest()
+    {
+        $this->_markTestAsRestOnly();
+
+        $nonExistentGroupId = '9999';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$nonExistentGroupId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => $nonExistentGroupId,
+            CustomerGroup::CODE => 'Updated Group REST Does Not Exist',
+            CustomerGroup::TAX_CLASS_ID => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception');
+        } catch (\Exception $e) {
+            $expectedMessage = '{"message":"No such entity with %fieldName = %fieldValue",'
+             . '"parameters":{"fieldName":"id","fieldValue":9999}';
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that creating a new group works via SOAP.
+     */
+    public function testCreateGroupSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Create Group SOAP',
+            'taxClassId' => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $groupId = $this->_webApiCall($serviceInfo, $requestData)[CustomerGroup::ID];
+        $this->assertNotNull($groupId);
+
+        $newGroup = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupId, $newGroup->getId(), "The group id does not match.");
+        $this->assertEquals($groupData[CustomerGroup::CODE], $newGroup->getCode(), "The group code does not match.");
+        $this->assertEquals(
+            $groupData['taxClassId'],
+            $newGroup->getTaxClassId(),
+            "The group tax class id does not match."
+        );
+    }
+
+    /**
+     * Verify that creating a new group with a duplicate code fails with an error via SOAP.
+     */
+    public function testCreateGroupDuplicateGroupSoap()
+    {
+        $this->_markTestAsSoapOnly();
+        $builder = Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\GroupDataBuilder');
+        $duplicateGroupCode = 'Duplicate Group Code SOAP';
+
+        $this->createGroup(
+            $builder->populateWithArray([
+                CustomerGroup::ID => null,
+                CustomerGroup::CODE => $duplicateGroupCode,
+                CustomerGroup::TAX_CLASS_ID => 3,
+            ])->create()
+        );
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => $duplicateGroupCode,
+            'taxClassId' => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $expectedMessage = 'Customer Group already exists.';
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that creating a new group works via SOAP if tax class id is empty, defaults 3.
+     */
+    public function testCreateGroupDefaultTaxClassIdSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Default Class Tax ID SOAP',
+            'taxClassId' => null,
+            'taxClassName' => null,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $groupResponseData = $this->_webApiCall($serviceInfo, $requestData);
+        $groupId = $groupResponseData[CustomerGroup::ID];
+        $this->assertNotNull($groupId);
+
+        $newGroup = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupId, $newGroup->getId(), "The group id does not match.");
+        $this->assertEquals($groupData[CustomerGroup::CODE], $newGroup->getCode(), "The group code does not match.");
+        $this->assertEquals(
+            GroupRepository::DEFAULT_TAX_CLASS_ID,
+            $newGroup->getTaxClassId(),
+            "The group tax class id does not match."
+        );
+    }
+
+    /**
+     * Verify that creating a new group without a code fails with an error.
+     */
+    public function testCreateGroupNoCodeExpectExceptionSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => null,
+            'taxClassId' => null,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                '%fieldName is a required field.',
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that creating a new group fails via SOAP if tax class id is invalid.
+     */
+    public function testCreateGroupInvalidTaxClassIdSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $invalidTaxClassId = 9999;
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => null,
+            CustomerGroup::CODE => 'Invalid Class Tax ID SOAP',
+            'taxClassId' => $invalidTaxClassId,
+        ];
+        $requestData = ['group' => $groupData];
+
+        $expectedMessage = 'Invalid value of "%value" provided for the %fieldName field.';
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that updating an existing group works via SOAP.
+     */
+    public function testUpdateGroupSoap()
+    {
+        $this->_markTestAsSoapOnly();
+        $builder = Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\GroupDataBuilder');
+        $groupId = $this->createGroup(
+            $builder->populateWithArray([
+                    CustomerGroup::ID => null,
+                    CustomerGroup::CODE => 'New Group SOAP',
+                    CustomerGroup::TAX_CLASS_ID => 3,
+                ])->create()
+        );
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => $groupId,
+            CustomerGroup::CODE => 'Updated Group SOAP',
+            'taxClassId' => 3,
+        ];
+        $this->_webApiCall($serviceInfo, ['group' => $groupData]);
+
+        $group = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupData[CustomerGroup::CODE], $group->getCode(), 'The group code did not change.');
+        $this->assertEquals(
+            $groupData['taxClassId'],
+            $group->getTaxClassId(),
+            'The group tax class id did not change'
+        );
+    }
+
+    /**
+     * Verify that updating a non-existing group throws an exception via SOAP.
+     */
+    public function testUpdateGroupNotExistingGroupSoap()
+    {
+        $this->_markTestAsSoapOnly();
+
+        $nonExistentGroupId = '9999';
+
+        $serviceInfo = [
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1Save',
+            ],
+        ];
+
+        $groupData = [
+            CustomerGroup::ID => $nonExistentGroupId,
+            CustomerGroup::CODE => 'Updated Non-Existent Group SOAP',
+            'taxClassId' => 3,
+        ];
+        $requestData = ['group' => $groupData];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * Verify that deleting an existing group works.
+     */
+    public function testDeleteGroupExists()
+    {
+        $builder = Bootstrap::getObjectManager()->create('Magento\Customer\Api\Data\GroupDataBuilder');
+        $groupId = $this->createGroup(
+            $builder->populateWithArray([
+                CustomerGroup::ID => null,
+                CustomerGroup::CODE => 'Delete Group',
+                CustomerGroup::TAX_CLASS_ID => 3,
+            ])->create()
+        );
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1DeleteById',
+            ],
+        ];
+
+        $requestData = [CustomerGroup::ID => $groupId];
+        $response = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($response, 'Expected response should be true.');
+
+        try {
+            $this->groupRepository->getById($groupId);
+            $this->fail('An expected NoSuchEntityException was not thrown.');
+        } catch (NoSuchEntityException $e) {
+            $exception = NoSuchEntityException::singleField(CustomerGroup::ID, $groupId);
+            $this->assertEquals(
+                $exception->getMessage(),
+                $e->getMessage(),
+                'Exception message does not match expected message.'
+            );
+        }
+    }
+
+    /**
+     * Verify that deleting an non-existing group works.
+     */
+    public function testDeleteGroupNotExists()
+    {
+        $groupId = 4200;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1DeleteById',
+            ],
+        ];
+
+        $requestData = [CustomerGroup::ID => $groupId];
+        $expectedMessage = NoSuchEntityException::MESSAGE_SINGLE_FIELD;
+        $expectedParameters = ['fieldName' => CustomerGroup::ID, 'fieldValue' => $groupId];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\SoapFault $e) {
+            $this->assertContains($expectedMessage, $e->getMessage(), "SoapFault does not contain expected message.");
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals($expectedMessage, $errorObj['message']);
+            $this->assertEquals($expectedParameters, $errorObj['parameters']);
+        }
+    }
+
+    /**
+     * Verify that the group with the specified Id cannot be deleted because it is the default group and a proper
+     * fault is returned.
+     */
+    public function testDeleteGroupCannotDelete()
+    {
+        $groupIdAssignedDefault = 1;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$groupIdAssignedDefault",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1DeleteById',
+            ],
+        ];
+
+        $requestData = [CustomerGroup::ID => $groupIdAssignedDefault];
+        $expectedMessage = "Cannot delete group.";
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+
+        $this->assertNotNull($this->groupRepository->getById($groupIdAssignedDefault));
+    }
+
+    /**
+     * Create a test group.
+     *
+     * @param CustomerGroup $group The group to create and save.
+     * @return int The group Id of the group that was created.
+     */
+    private function createGroup($group)
+    {
+        $groupId = $this->groupRepository->save($group)->getId();
+        $this->assertNotNull($groupId);
+
+        $newGroup = $this->groupRepository->getById($groupId);
+        $this->assertEquals($groupId, $newGroup->getId(), 'The group id does not match.');
+        $this->assertEquals($group->getCode(), $newGroup->getCode(), 'The group code does not match.');
+        $this->assertEquals(
+            $group->getTaxClassId(),
+            $newGroup->getTaxClassId(),
+            'The group tax class id does not match.'
+        );
+
+        $this->groupRegistry->remove($groupId);
+
+        return $groupId;
+    }
+
+    /**
+     * Data provider for testSearchGroups
+     */
+    public function testSearchGroupsDataProvider()
+    {
+        return [
+            ['tax_class_id', '3', []],
+            ['tax_class_id', '0', null],
+            ['code', md5(mt_rand(0, 10000000000) . time()), null],
+            [
+                'id',
+                '0',
+                [
+                    'id' => '0',
+                    'code' => 'NOT LOGGED IN',
+                    'tax_class_id' => '3',
+                    'tax_class_name' => 'Retail Customer'
+                ]
+            ],
+            [
+                'code',
+                'General',
+                [
+                    'id' => '1',
+                    'code' => 'General',
+                    'tax_class_id' => '3',
+                    'tax_class_name' => 'Retail Customer'
+                ]
+            ],
+            [
+                'id',
+                '2',
+                [
+                    'id' => '2',
+                    'code' => 'Wholesale',
+                    'tax_class_id' => '3',
+                    'tax_class_name' => 'Retail Customer'
+                ]
+            ],
+            [
+                'code',
+                'Retailer',
+                [
+                    'id' => '3',
+                    'code' => 'Retailer',
+                    'tax_class_id' => '3',
+                    'tax_class_name' => 'Retail Customer'
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * Test search customer group
+     *
+     * @param string $filterField Customer Group field to filter by
+     * @param string $filterValue Value of the field to be filtered by
+     * @param array $expectedResult Expected search result
+     *
+     * @dataProvider testSearchGroupsDataProvider
+     */
+    public function testSearchGroups($filterField, $filterValue, $expectedResult)
+    {
+        $filterBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $searchCriteriaBuilder =  Bootstrap::getObjectManager()
+            ->create('Magento\Framework\Api\SearchCriteriaBuilder');
+        $filter = $filterBuilder
+                    ->setField($filterField)
+                    ->setValue($filterValue)
+                    ->create();
+        $searchCriteriaBuilder->addFilter([$filter]);
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/search",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => 'customerGroupRepositoryV1GetList',
+            ],
+        ];
+
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+
+        $searchResult = $this->_webApiCall($serviceInfo, $requestData);
+
+        if (is_null($expectedResult)) {
+            $this->assertEquals(0, $searchResult['total_count']);
+        } elseif (is_array($expectedResult)) {
+            $this->assertGreaterThan(0, $searchResult['total_count']);
+            if (!empty($expectedResult)) {
+                $this->assertEquals($expectedResult, $searchResult['items'][0]);
+            }
+        }
+    }
+
+    /**
+     * Test search customer group using GET
+     *
+     * @param string $filterField Customer Group field to filter by
+     * @param string $filterValue Value of the field to be filtered by
+     * @param array $expectedResult Expected search result
+     *
+     * @dataProvider testSearchGroupsDataProvider
+     */
+    public function testSearchGroupsWithGET($filterField, $filterValue, $expectedResult)
+    {
+        $this->_markTestAsRestOnly('SOAP is covered in ');
+        $filterBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
+        $searchCriteriaBuilder =  Bootstrap::getObjectManager()
+            ->create('Magento\Framework\Api\SearchCriteriaBuilder');
+        $filter = $filterBuilder
+            ->setField($filterField)
+            ->setValue($filterValue)
+            ->create();
+        $searchCriteriaBuilder->addFilter([$filter]);
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchQueryString = http_build_query($requestData);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+        $searchResult = $this->_webApiCall($serviceInfo);
+
+        if (is_null($expectedResult)) {
+            $this->assertEquals(0, $searchResult['total_count']);
+        } elseif (is_array($expectedResult)) {
+            $this->assertGreaterThan(0, $searchResult['total_count']);
+            if (!empty($expectedResult)) {
+                $this->assertEquals($expectedResult, $searchResult['items'][0]);
+            }
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bade51570029bb3a5755c18db7e84ca553961d7
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/ReadServiceTest.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Downloadable\Service\V1\DownloadableLink;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * @dataProvider getListForAbsentProductProvider()
+     */
+    public function testGetListForAbsentProduct($urlTail, $method)
+    {
+        $sku = 'absent-product' . time();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $sku . $urlTail,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkReadServiceV1' . $method,
+            ],
+        ];
+
+        $requestData = ['productSku' => $sku];
+
+        $expectedMessage = 'Requested product doesn\'t exist';
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\SoapFault $e) {
+            $this->assertEquals($expectedMessage, $e->getMessage());
+        } catch (\Exception $e) {
+            $this->assertContains($expectedMessage, $e->getMessage());
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @dataProvider getListForAbsentProductProvider
+     */
+    public function testGetListForSimpleProduct($urlTail, $method)
+    {
+        $sku = 'simple';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $sku . $urlTail,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkReadServiceV1' . $method,
+            ],
+        ];
+
+        $requestData = ['productSku' => $sku];
+
+        $list = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEmpty($list);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     * @dataProvider getListForAbsentProductProvider
+     */
+    public function testGetList($urlTail, $method, $expectations)
+    {
+        $sku = 'downloadable-product';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/' . $sku . $urlTail,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkReadServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkReadServiceV1' . $method,
+            ],
+        ];
+
+        $requestData = ['productSku' => $sku];
+
+        $list = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals(1, count($list));
+
+        $link = reset($list);
+        foreach ($expectations['fields'] as $index => $value) {
+            $this->assertEquals($value, $link[$index]);
+        }
+
+        foreach ($expectations['resources'] as $name => $fields) {
+            $this->assertNotEmpty($link[$name]);
+            $this->assertEquals($fields['file'], $link[$name]['file']);
+            $this->assertEquals($fields['type'], $link[$name]['type']);
+        }
+    }
+
+    public function getListForAbsentProductProvider()
+    {
+        $sampleIndex = 'sample_resource';
+        $linkIndex = 'link_resource';
+
+        $linkExpectation = [
+            'fields' => [
+                'shareable' => 2,
+                'price' => 15,
+                'number_of_downloads' => 15,
+            ],
+            'resources' => [
+                $sampleIndex => [
+                    'file' => '/n/d/jellyfish_1_3.jpg',
+                    'type' => 'file',
+                ],
+                $linkIndex => [
+                    'file' => '/j/e/jellyfish_2_4.jpg',
+                    'type' => 'file',
+                ],
+            ],
+        ];
+
+        $sampleExpectation = [
+            'fields' => [
+                'title' => 'Downloadable Product Sample Title',
+                'sort_order' => 0,
+            ],
+            'resources' => [
+                $sampleIndex => [
+                    'file' => '/f/u/jellyfish_1_4.jpg',
+                    'type' => 'file',
+                ],
+            ],
+        ];
+
+        return [
+            'links' => [
+                '/downloadable-links',
+                'GetLinks',
+                $linkExpectation,
+            ],
+            'samples' => [
+                '/downloadable-links/samples',
+                'GetSamples',
+                $sampleExpectation,
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f96f1951755853aa409493058a9164cc0b68601
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/WriteServiceTest.php
@@ -0,0 +1,796 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Downloadable\Service\V1\DownloadableLink;
+
+use Magento\Catalog\Model\Product;
+use Magento\Downloadable\Model\Link;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    /**
+
+     * @var array
+     */
+    protected $createServiceInfo;
+
+    /**
+     * @var array
+     */
+    protected $updateServiceInfo;
+
+    /**
+     * @var array
+     */
+    protected $deleteServiceInfo;
+
+    /**
+     * @var string
+     */
+    protected $testImagePath;
+
+    protected function setUp()
+    {
+        $this->createServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/downloadable-product/downloadable-links',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkWriteServiceV1Create',
+            ],
+        ];
+
+        $this->updateServiceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkWriteServiceV1Update',
+            ],
+        ];
+
+        $this->deleteServiceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableLinkWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableLinkWriteServiceV1Delete',
+            ],
+        ];
+
+        $this->testImagePath = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'test_image.jpg';
+    }
+
+    /**
+     * Retrieve product that was updated by test
+     *
+     * @param bool $isScopeGlobal if true product store ID will be set to 0
+     * @return Product
+     */
+    protected function getTargetProduct($isScopeGlobal = false)
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $product = $objectManager->get('Magento\Catalog\Model\ProductFactory')->create()->load(1);
+        if ($isScopeGlobal) {
+            $product->setStoreId(0);
+        }
+        return $product;
+    }
+
+    /**
+     * Retrieve product link by its ID (or first link if ID is not specified)
+     *
+     * @param Product $product
+     * @param int|null $linkId
+     * @return Link|null
+     */
+    protected function getTargetLink(Product $product, $linkId = null)
+    {
+        $links = $product->getTypeInstance()->getLinks($product);
+        if (!is_null($linkId)) {
+            return isset($links[$linkId]) ? $links[$linkId] : null;
+        }
+        // return first link
+        return reset($links);
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateUploadsProvidedFileContent()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Title',
+                'sort_order' => 1,
+                'price' => 10.1,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'file',
+                'link_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'image.jpg',
+                ],
+                'sample_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'image.jpg',
+                ],
+                'sample_type' => 'file',
+            ],
+        ];
+
+        $newLinkId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $globalScopeLink = $this->getTargetLink($this->getTargetProduct(true), $newLinkId);
+        $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId);
+        $this->assertNotNull($link);
+        $this->assertEquals($requestData['linkContent']['title'], $link->getTitle());
+        $this->assertEquals($requestData['linkContent']['title'], $globalScopeLink->getTitle());
+        $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder());
+        $this->assertEquals($requestData['linkContent']['price'], $link->getPrice());
+        $this->assertEquals($requestData['linkContent']['price'], $globalScopeLink->getPrice());
+        $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable());
+        $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads());
+        $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType());
+        $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType());
+        $this->assertStringEndsWith('.jpg', $link->getSampleFile());
+        $this->assertStringEndsWith('.jpg', $link->getLinkFile());
+        $this->assertNull($link->getLinkUrl());
+        $this->assertNull($link->getSampleUrl());
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateSavesPriceAndTitleInStoreViewScope()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Store View Title',
+                'sort_order' => 1,
+                'price' => 150,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_url' => 'http://www.example.com/',
+                'link_type' => 'url',
+                'sample_url' => 'http://www.sample.example.com/',
+                'sample_type' => 'url',
+            ],
+        ];
+
+        $newLinkId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId);
+        $globalScopeLink = $this->getTargetLink($this->getTargetProduct(true), $newLinkId);
+        $this->assertNotNull($link);
+        $this->assertEquals($requestData['linkContent']['title'], $link->getTitle());
+        $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder());
+        $this->assertEquals($requestData['linkContent']['price'], $link->getPrice());
+        $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable());
+        $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads());
+        $this->assertEquals($requestData['linkContent']['link_url'], $link->getLinkUrl());
+        $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType());
+        $this->assertEquals($requestData['linkContent']['sample_url'], $link->getSampleUrl());
+        $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType());
+        $this->assertEmpty($globalScopeLink->getTitle());
+        $this->assertEmpty($globalScopeLink->getPrice());
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateSavesProvidedUrls()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link with URL resources',
+                'sort_order' => 1,
+                'price' => 10.1,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_url' => 'http://www.example.com/',
+                'link_type' => 'url',
+                'sample_url' => 'http://www.sample.example.com/',
+                'sample_type' => 'url',
+            ],
+        ];
+
+        $newLinkId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $link = $this->getTargetLink($this->getTargetProduct(), $newLinkId);
+        $this->assertNotNull($link);
+        $this->assertEquals($requestData['linkContent']['title'], $link->getTitle());
+        $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder());
+        $this->assertEquals($requestData['linkContent']['price'], $link->getPrice());
+        $this->assertEquals($requestData['linkContent']['shareable'], $link->getIsShareable());
+        $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads());
+        $this->assertEquals($requestData['linkContent']['link_url'], $link->getLinkUrl());
+        $this->assertEquals($requestData['linkContent']['link_type'], $link->getLinkType());
+        $this->assertEquals($requestData['linkContent']['sample_type'], $link->getSampleType());
+        $this->assertEquals($requestData['linkContent']['sample_url'], $link->getSampleUrl());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid link type.
+     */
+    public function testCreateThrowsExceptionIfLinkTypeIsNotSpecified()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link with URL resources',
+                'sort_order' => 1,
+                'price' => 10.1,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided content must be valid base64 encoded data.
+     */
+    public function testCreateThrowsExceptionIfLinkFileContentIsNotAValidBase64EncodedString()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => 10,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'url',
+                'link_url' => 'http://www.example.com/',
+                'sample_type' => 'file',
+                'sample_file' => [
+                    'data' => 'not_a_base64_encoded_content',
+                    'name' => 'image.jpg',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided content must be valid base64 encoded data.
+     */
+    public function testCreateThrowsExceptionIfSampleFileContentIsNotAValidBase64EncodedString()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => 10,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'file',
+                'link_file' => [
+                    'data' => 'not_a_base64_encoded_content',
+                    'name' => 'image.jpg',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided file name contains forbidden characters.
+     */
+    public function testCreateThrowsExceptionIfLinkFileNameContainsForbiddenCharacters()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Title',
+                'sort_order' => 15,
+                'price' => 10,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'file',
+                'link_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'name/with|forbidden{characters',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided file name contains forbidden characters.
+     */
+    public function testCreateThrowsExceptionIfSampleFileNameContainsForbiddenCharacters()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => 10,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'url',
+                'link_url' => 'http://www.example.com/',
+                'sample_type' => 'file',
+                'sample_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'name/with|forbidden{characters',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Link URL must have valid format.
+     */
+    public function testCreateThrowsExceptionIfLinkUrlHasWrongFormat()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => 10,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'link_type' => 'url',
+                'link_url' => 'http://example<.>com/',
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sample URL must have valid format.
+     */
+    public function testCreateThrowsExceptionIfSampleUrlHasWrongFormat()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => 150,
+                'shareable' => true,
+                'number_of_downloads' => 0,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example<.>com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Link price must have numeric positive value.
+     * @dataProvider getInvalidLinkPrice
+     */
+    public function testCreateThrowsExceptionIfLinkPriceIsInvalid($linkPrice)
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 1,
+                'price' => $linkPrice,
+                'shareable' => true,
+                'number_of_downloads' => 0,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @return array
+     */
+    public function getInvalidLinkPrice()
+    {
+        return [
+            ['string_value'],
+            [-1.5],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sort order must be a positive integer.
+     * @dataProvider getInvalidSortOrder
+     */
+    public function testCreateThrowsExceptionIfSortOrderIsInvalid($sortOrder)
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => $sortOrder,
+                'price' => 10,
+                'shareable' => false,
+                'number_of_downloads' => 0,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @return array
+     */
+    public function getInvalidSortOrder()
+    {
+        return [
+            [-1],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Number of downloads must be a positive integer.
+     * @dataProvider getInvalidNumberOfDownloads
+     */
+    public function testCreateThrowsExceptionIfNumberOfDownloadsIsInvalid($numberOfDownloads)
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 0,
+                'price' => 10,
+                'shareable' => false,
+                'number_of_downloads' => $numberOfDownloads,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @return array
+     */
+    public function getInvalidNumberOfDownloads()
+    {
+        return [
+            [-1],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Product type of the product must be 'downloadable'.
+     */
+    public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable()
+    {
+        $this->createServiceInfo['rest']['resourcePath'] = '/V1/products/simple/downloadable-links';
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'simple',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 50,
+                'price' => 200,
+                'shareable' => false,
+                'number_of_downloads' => 10,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testCreateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->createServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links';
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'wrong-sku',
+            'linkContent' => [
+                'title' => 'Link Title',
+                'sort_order' => 15,
+                'price' => 200,
+                'shareable' => true,
+                'number_of_downloads' => 100,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+                'link_type' => 'url',
+                'link_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testUpdate()
+    {
+        $linkId = $this->getTargetLink($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'linkId' => $linkId,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+                'price' => 100.10,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+        $link = $this->getTargetLink($this->getTargetProduct(), $linkId);
+        $this->assertNotNull($link);
+        $this->assertEquals($requestData['linkContent']['title'], $link->getTitle());
+        $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder());
+        $this->assertEquals($requestData['linkContent']['price'], $link->getPrice());
+        $this->assertEquals($requestData['linkContent']['shareable'], (bool)$link->getIsShareable());
+        $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testUpdateSavesDataInGlobalScopeAndDoesNotAffectValuesStoredInStoreViewScope()
+    {
+        $originalLink = $this->getTargetLink($this->getTargetProduct());
+        $linkId = $originalLink->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'linkId' => $linkId,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+                'price' => 100.10,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+        $link = $this->getTargetLink($this->getTargetProduct(), $linkId);
+        $globalScopeLink = $this->getTargetLink($this->getTargetProduct(true), $linkId);
+        $this->assertNotNull($link);
+        // Title and price were set on store view level in fixture so they must be the same
+        $this->assertEquals($originalLink->getTitle(), $link->getTitle());
+        $this->assertEquals($originalLink->getPrice(), $link->getPrice());
+        $this->assertEquals($requestData['linkContent']['title'], $globalScopeLink->getTitle());
+        $this->assertEquals($requestData['linkContent']['price'], $globalScopeLink->getPrice());
+        $this->assertEquals($requestData['linkContent']['sort_order'], $link->getSortOrder());
+        $this->assertEquals($requestData['linkContent']['shareable'], (bool)$link->getIsShareable());
+        $this->assertEquals($requestData['linkContent']['number_of_downloads'], $link->getNumberOfDownloads());
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testUpdateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links/1';
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'linkId' => 1,
+            'productSku' => 'wrong-sku',
+            'linkContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+                'price' => 100.10,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no downloadable link with provided ID.
+     */
+    public function testUpdateThrowsExceptionIfThereIsNoDownloadableLinkWithGivenId()
+    {
+        $linkId = 9999;
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'linkId' => 9999,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Title',
+                'sort_order' => 2,
+                'price' => 100.10,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Link price must have numeric positive value.
+     * @dataProvider getInvalidLinkPrice
+     */
+    public function testUpdateThrowsExceptionIfLinkPriceIsInvalid($linkPrice)
+    {
+        $linkId = $this->getTargetLink($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'linkId' => $linkId,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Updated Link Title',
+                'sort_order' => 2,
+                'price' => $linkPrice,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sort order must be a positive integer.
+     * @dataProvider getInvalidSortOrder
+     */
+    public function testUpdateThrowsExceptionIfSortOrderIsInvalid($sortOrder)
+    {
+        $linkId = $this->getTargetLink($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'linkId' => $linkId,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Updated Link Title',
+                'sort_order' => $sortOrder,
+                'price' => 100.50,
+                'shareable' => false,
+                'number_of_downloads' => 50,
+            ],
+        ];
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Number of downloads must be a positive integer.
+     * @dataProvider getInvalidNumberOfDownloads
+     */
+    public function testUpdateThrowsExceptionIfNumberOfDownloadsIsInvalid($numberOfDownloads)
+    {
+        $linkId = $this->getTargetLink($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/{$linkId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'linkId' => $linkId,
+            'productSku' => 'downloadable-product',
+            'linkContent' => [
+                'title' => 'Updated Link Title',
+                'sort_order' => 200,
+                'price' => 100.50,
+                'shareable' => false,
+                'number_of_downloads' => $numberOfDownloads,
+            ],
+        ];
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testDelete()
+    {
+        $linkId = $this->getTargetLink($this->getTargetProduct())->getId();
+        $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/{$linkId}";
+        $requestData = [
+            'linkId' => $linkId,
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->deleteServiceInfo, $requestData));
+        $link = $this->getTargetLink($this->getTargetProduct(), $linkId);
+        $this->assertNull($link);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no downloadable link with provided ID.
+     */
+    public function testDeleteThrowsExceptionIfThereIsNoDownloadableLinkWithGivenId()
+    {
+        $linkId = 9999;
+        $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/{$linkId}";
+        $requestData = [
+            'linkId' => $linkId,
+        ];
+
+        $this->_webApiCall($this->deleteServiceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/_files/test_image.jpg b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/_files/test_image.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ad6b747f73dd9d20f73b8fc780e74d1ff7952762
Binary files /dev/null and b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableLink/_files/test_image.jpg differ
diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableSample/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableSample/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..542e1527f8eb58111d8768c4d16708827a6374f1
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Service/V1/DownloadableSample/WriteServiceTest.php
@@ -0,0 +1,509 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Downloadable\Service\V1\DownloadableSample;
+
+use Magento\Catalog\Model\Product;
+use Magento\Downloadable\Model\Sample;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    /**
+     * @var array
+     */
+    protected $createServiceInfo;
+
+    /**
+     * @var string
+     */
+    protected $testImagePath;
+
+    /**
+     * @var array
+     */
+    protected $updateServiceInfo;
+
+    /**
+     * @var array
+     */
+    protected $deleteServiceInfo;
+
+    protected function setUp()
+    {
+        $this->createServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/products/downloadable-product/downloadable-links/samples',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableSampleWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableSampleWriteServiceV1Create',
+            ],
+        ];
+
+        $this->updateServiceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableSampleWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableSampleWriteServiceV1Update',
+            ],
+        ];
+
+        $this->deleteServiceInfo = [
+            'rest' => [
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'downloadableDownloadableSampleWriteServiceV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'downloadableDownloadableSampleWriteServiceV1Delete',
+            ],
+        ];
+
+        $this->testImagePath = __DIR__
+            . str_replace('/', DIRECTORY_SEPARATOR, '/../DownloadableLink/_files/test_image.jpg');
+    }
+
+    /**
+     * Retrieve product that was updated by test
+     *
+     * @param bool $isScopeGlobal if true product store ID will be set to 0
+     * @return Product
+     */
+    protected function getTargetProduct($isScopeGlobal = false)
+    {
+        $product = Bootstrap::getObjectManager()->get('Magento\Catalog\Model\ProductFactory')->create()->load(1);
+        if ($isScopeGlobal) {
+            $product->setStoreId(0);
+        }
+        return $product;
+    }
+
+    /**
+     * Retrieve product sample by its ID (or first sample if ID is not specified)
+     *
+     * @param Product $product
+     * @param int|null $sampleId
+     * @return Sample|null
+     */
+    protected function getTargetSample(Product $product, $sampleId = null)
+    {
+        /** @var $samples \Magento\Downloadable\Model\Resource\Sample\Collection */
+        $samples = $product->getTypeInstance()->getSamples($product);
+        if (!is_null($sampleId)) {
+            /* @var $sample \Magento\Downloadable\Model\Sample  */
+            foreach ($samples as $sample) {
+                if ($sample->getId() == $sampleId) {
+                    return $sample;
+                }
+            }
+            return null;
+        }
+        // return first sample
+        return $samples->getFirstItem();
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateUploadsProvidedFileContent()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Title',
+                'sort_order' => 1,
+                'sample_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'image.jpg',
+                ],
+                'sample_type' => 'file',
+            ],
+        ];
+
+        $newSampleId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $globalScopeSample = $this->getTargetSample($this->getTargetProduct(true), $newSampleId);
+        $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId);
+        $this->assertNotNull($sample);
+        $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['title'], $globalScopeSample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder());
+        $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType());
+        $this->assertStringEndsWith('.jpg', $sample->getSampleFile());
+        $this->assertNull($sample->getSampleUrl());
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateSavesTitleInStoreViewScope()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Store View Title',
+                'sort_order' => 1,
+                'sample_url' => 'http://www.sample.example.com/',
+                'sample_type' => 'url',
+            ],
+        ];
+
+        $newSampleId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId);
+        $globalScopeSample = $this->getTargetSample($this->getTargetProduct(true), $newSampleId);
+        $this->assertNotNull($sample);
+        $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder());
+        $this->assertEquals($requestData['sampleContent']['sample_url'], $sample->getSampleUrl());
+        $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType());
+        $this->assertEmpty($globalScopeSample->getTitle());
+    }
+
+    /**
+     *  @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     */
+    public function testCreateSavesProvidedUrls()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Sample with URL resource',
+                'sort_order' => 1,
+                'sample_url' => 'http://www.sample.example.com/',
+                'sample_type' => 'url',
+            ],
+        ];
+
+        $newSampleId = $this->_webApiCall($this->createServiceInfo, $requestData);
+        $sample = $this->getTargetSample($this->getTargetProduct(), $newSampleId);
+        $this->assertNotNull($sample);
+        $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder());
+        $this->assertEquals($requestData['sampleContent']['sample_type'], $sample->getSampleType());
+        $this->assertEquals($requestData['sampleContent']['sample_url'], $sample->getSampleUrl());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid sample type.
+     */
+    public function testCreateThrowsExceptionIfSampleTypeIsNotSpecified()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Sample with URL resource',
+                'sort_order' => 1,
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided content must be valid base64 encoded data.
+     */
+    public function testCreateThrowsExceptionIfSampleFileContentIsNotAValidBase64EncodedString()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Sample Title',
+                'sort_order' => 1,
+                'sample_type' => 'file',
+                'sample_file' => [
+                    'data' => 'not_a_base64_encoded_content',
+                    'name' => 'image.jpg',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Provided file name contains forbidden characters.
+     */
+    public function testCreateThrowsExceptionIfSampleFileNameContainsForbiddenCharacters()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Title',
+                'sort_order' => 15,
+                'sample_type' => 'file',
+                'sample_file' => [
+                    'data' => base64_encode(file_get_contents($this->testImagePath)),
+                    'name' => 'name/with|forbidden{characters',
+                ],
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sample URL must have valid format.
+     */
+    public function testCreateThrowsExceptionIfSampleUrlHasWrongFormat()
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Sample Title',
+                'sort_order' => 1,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example<.>com/',
+            ],
+        ];
+
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sort order must be a positive integer.
+     * @dataProvider getInvalidSortOrder
+     */
+    public function testCreateThrowsExceptionIfSortOrderIsInvalid($sortOrder)
+    {
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Sample Title',
+                'sort_order' => $sortOrder,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @return array
+     */
+    public function getInvalidSortOrder()
+    {
+        return [
+            [-1],
+        ];
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Product type of the product must be 'downloadable'.
+     */
+    public function testCreateThrowsExceptionIfTargetProductTypeIsNotDownloadable()
+    {
+        $this->createServiceInfo['rest']['resourcePath']
+            = '/V1/products/simple/downloadable-links/samples';
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'simple',
+            'sampleContent' => [
+                'title' => 'Sample Title',
+                'sort_order' => 50,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testCreateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->createServiceInfo['rest']['resourcePath']
+            = '/V1/products/wrong-sku/downloadable-links/samples';
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'productSku' => 'wrong-sku',
+            'sampleContent' => [
+                'title' => 'Title',
+                'sort_order' => 15,
+                'sample_type' => 'url',
+                'sample_url' => 'http://example.com/',
+            ],
+        ];
+        $this->_webApiCall($this->createServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     */
+    public function testUpdate()
+    {
+        $sampleId = $this->getTargetSample($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'sampleId' => $sampleId,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+            ],
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+        $sample = $this->getTargetSample($this->getTargetProduct(), $sampleId);
+        $this->assertNotNull($sample);
+        $this->assertEquals($requestData['sampleContent']['title'], $sample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     */
+    public function testUpdateSavesDataInGlobalScopeAndDoesNotAffectValuesStoredInStoreViewScope()
+    {
+        $originalSample = $this->getTargetSample($this->getTargetProduct());
+        $sampleId = $originalSample->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'sampleId' => $sampleId,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+            ],
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->updateServiceInfo, $requestData));
+        $sample = $this->getTargetSample($this->getTargetProduct(), $sampleId);
+        $globalScopeSample = $this->getTargetSample($this->getTargetProduct(true), $sampleId);
+        $this->assertNotNull($sample);
+        // Title was set on store view level in fixture so it must be the same
+        $this->assertEquals($originalSample->getTitle(), $sample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['title'], $globalScopeSample->getTitle());
+        $this->assertEquals($requestData['sampleContent']['sort_order'], $sample->getSortOrder());
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Requested product doesn't exist
+     */
+    public function testUpdateThrowsExceptionIfTargetProductDoesNotExist()
+    {
+        $this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong-sku/downloadable-links/samples/1';
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'sampleId' => 1,
+            'productSku' => 'wrong-sku',
+            'sampleContent' => [
+                'title' => 'Updated Title',
+                'sort_order' => 2,
+            ],
+        ];
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no downloadable sample with provided ID.
+     */
+    public function testUpdateThrowsExceptionIfThereIsNoDownloadableSampleWithGivenId()
+    {
+        $sampleId = 9999;
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'isGlobalScopeContent' => true,
+            'sampleId' => 9999,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Title',
+                'sort_order' => 2,
+            ],
+        ];
+
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     * @expectedException \Exception
+     * @expectedExceptionMessage Sort order must be a positive integer.
+     * @dataProvider getInvalidSortOrder
+     */
+    public function testUpdateThrowsExceptionIfSortOrderIsInvalid($sortOrder)
+    {
+        $sampleId = $this->getTargetSample($this->getTargetProduct())->getId();
+        $this->updateServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-product/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'isGlobalScopeContent' => false,
+            'sampleId' => $sampleId,
+            'productSku' => 'downloadable-product',
+            'sampleContent' => [
+                'title' => 'Updated Sample Title',
+                'sort_order' => $sortOrder,
+            ],
+        ];
+        $this->_webApiCall($this->updateServiceInfo, $requestData);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php
+     */
+    public function testDelete()
+    {
+        $sampleId = $this->getTargetSample($this->getTargetProduct())->getId();
+        $this->deleteServiceInfo['rest']['resourcePath'] = "/V1/products/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'sampleId' => $sampleId,
+        ];
+
+        $this->assertTrue($this->_webApiCall($this->deleteServiceInfo, $requestData));
+        $sample = $this->getTargetSample($this->getTargetProduct(), $sampleId);
+        $this->assertNull($sample);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage There is no downloadable sample with provided ID.
+     */
+    public function testDeleteThrowsExceptionIfThereIsNoDownloadableSampleWithGivenId()
+    {
+        $sampleId = 9999;
+        $this->deleteServiceInfo['rest']['resourcePath']
+            = "/V1/products/downloadable-links/samples/{$sampleId}";
+        $requestData = [
+            'sampleId' => $sampleId,
+        ];
+
+        $this->_webApiCall($this->deleteServiceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..83166269a7c332013e98eb9bbaf6f122fd3dd07d
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php
@@ -0,0 +1,235 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Eav\Api;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class AttributeSetManagementTest extends WebapiAbstract
+{
+    /**
+     * @var array
+     */
+    private $createServiceInfo;
+
+    protected function setUp()
+    {
+        $this->createServiceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetManagementV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetManagementV1Create',
+            ],
+        ];
+    }
+
+    public function testCreate()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 500,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $result = $this->_webApiCall($this->createServiceInfo, $arguments);
+        $this->assertNotNull($result);
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $this->assertNotNull($attributeSet);
+        $this->assertEquals($attributeSet->getId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $entityType->getId());
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+        $this->assertEquals($attributeSet->getSortOrder(), 500);
+
+        // Clean up database
+        $attributeSet->delete();
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid value
+     */
+    public function testCreateThrowsExceptionIfGivenAttributeSetAlreadyHasId()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_id' => 1,
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 100,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid value
+     */
+    public function testCreateThrowsExceptionIfGivenSkeletonIdIsInvalid()
+    {
+        $entityTypeCode = 'catalog_product';
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 200,
+            ],
+            'skeletonId' => 0,
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage No such entity
+     */
+    public function testCreateThrowsExceptionIfGivenSkeletonAttributeSetDoesNotExist()
+    {
+        $attributeSetName = 'new_attribute_set';
+        $entityTypeCode = 'catalog_product';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 300,
+            ],
+            'skeletonId' => 9999,
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Invalid entity_type specified: invalid_entity_type
+     */
+    public function testCreateThrowsExceptionIfGivenEntityTypeDoesNotExist()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'new_attribute_set';
+
+        $arguments = [
+            'entityTypeCode' => 'invalid_entity_type',
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 400,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Attribute set name is empty.
+     */
+    public function testCreateThrowsExceptionIfAttributeSetNameIsEmpty()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = '';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 500,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+        $this->_webApiCall($this->createServiceInfo, $arguments);
+    }
+
+    public function testCreateThrowsExceptionIfAttributeSetWithGivenNameAlreadyExists()
+    {
+        $entityTypeCode = 'catalog_product';
+        $entityType = $this->getEntityTypeByCode($entityTypeCode);
+        $attributeSetName = 'Default';
+        $expectedMessage = 'An attribute set with the "Default" name already exists.';
+
+        $arguments = [
+            'entityTypeCode' => $entityTypeCode,
+            'attributeSet' => [
+                'attribute_set_name' => $attributeSetName,
+                'sort_order' => 550,
+            ],
+            'skeletonId' => $entityType->getDefaultAttributeSetId(),
+        ];
+
+        try {
+            $this->_webApiCall($this->createServiceInfo, $arguments);
+            $this->fail("Expected exception");
+        } catch (\SoapFault $e) {
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "SoapFault does not contain expected message."
+            );
+        } catch (\Exception $e) {
+            $errorObj = $this->processRestExceptionResult($e);
+            $this->assertEquals(
+                $expectedMessage,
+                $errorObj['message']
+            );
+            $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        }
+    }
+
+    /**
+     * Retrieve attribute set based on given name.
+     * This utility methods assumes that there is only one attribute set with given name,
+     *
+     * @param string $attributeSetName
+     * @return \Magento\Eav\Model\Entity\Attribute\Set|null
+     */
+    protected function getAttributeSetByName($attributeSetName)
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
+        $attributeSet = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Set')
+            ->load($attributeSetName, 'attribute_set_name');
+        if ($attributeSet->getId() === null) {
+            return null;
+        }
+        return $attributeSet;
+    }
+
+    /**
+     * Retrieve entity type based on given code.
+     *
+     * @param string $entityTypeCode
+     * @return \Magento\Eav\Model\Entity\Type|null
+     */
+    protected function getEntityTypeByCode($entityTypeCode)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Type $entityType */
+        $entityType = $objectManager->create('Magento\Eav\Model\Config')
+            ->getEntityType($entityTypeCode);
+        return $entityType;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a7024a290a2937bd165d246c01ff0d578027906
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetRepositoryTest.php
@@ -0,0 +1,260 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Eav\Api;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class AttributeSetRepositoryTest extends WebapiAbstract
+{
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testGet()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $attributeSetId = $attributeSet->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1Get',
+            ],
+        ];
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $result = $this->_webApiCall($serviceInfo, $arguments);
+        $this->assertNotNull($result);
+        $this->assertEquals($attributeSet->getId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testGetThrowsExceptionIfRequestedAttributeSetDoesNotExist()
+    {
+        $attributeSetId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1Get',
+            ],
+        ];
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->_webApiCall($serviceInfo, $arguments);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testSave()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1Save',
+            ],
+        ];
+
+        $updatedSortOrder = $attributeSet->getSortOrder() + 200;
+
+        $arguments = [
+            'attributeSet' => [
+                'attribute_set_id' => $attributeSet->getId(),
+                // name is the same, because it is used by fixture rollback script
+                'attribute_set_name' => $attributeSet->getAttributeSetName(),
+                'entity_type_id' => $attributeSet->getEntityTypeId(),
+                'sort_order' => $updatedSortOrder,
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $arguments);
+        $this->assertNotNull($result);
+        // Reload attribute set data
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $this->assertEquals($attributeSet->getAttributeSetId(), $result['attribute_set_id']);
+        $this->assertEquals($attributeSet->getAttributeSetName(), $result['attribute_set_name']);
+        $this->assertEquals($attributeSet->getEntityTypeId(), $result['entity_type_id']);
+        $this->assertEquals($updatedSortOrder, $result['sort_order']);
+        $this->assertEquals($attributeSet->getSortOrder(), $result['sort_order']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testDeleteById()
+    {
+        $attributeSetName = 'empty_attribute_set';
+        $attributeSet = $this->getAttributeSetByName($attributeSetName);
+        $attributeSetId = $attributeSet->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1DeleteById',
+            ],
+        ];
+
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $arguments));
+        $this->assertNull($this->getAttributeSetByName($attributeSetName));
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Default attribute set can not be deleted
+     */
+    public function testDeleteByIdDefaultAttributeSet()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Config */
+        $eavConfig = $objectManager->create('Magento\Eav\Model\Config');
+
+        $defaultAttributeSetId = $eavConfig
+            ->getEntityType(\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE)
+            ->getDefaultAttributeSetId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/' . $defaultAttributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1DeleteById',
+            ],
+        ];
+
+        $arguments = [
+            'attributeSetId' => $defaultAttributeSetId,
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $arguments));
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testDeleteByIdThrowsExceptionIfRequestedAttributeSetDoesNotExist()
+    {
+        $attributeSetId = 9999;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/' . $attributeSetId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1DeleteById',
+            ],
+        ];
+
+        $arguments = [
+            'attributeSetId' => $attributeSetId,
+        ];
+        $this->_webApiCall($serviceInfo, $arguments);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Eav/_files/empty_attribute_set.php
+     */
+    public function testGetList()
+    {
+        $searchCriteria = [
+            'searchCriteria' => [
+                'filter_groups' => [
+                    [
+                        'filters' => [
+                            [
+                                'field' => 'entity_type_code',
+                                'value' => 'catalog_product',
+                                'condition_type' => 'eq',
+                            ],
+                        ],
+                    ],
+                ],
+                'current_page' => 1,
+                'page_size' => 2,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/eav/attribute-sets/list',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => 'eavAttributeSetRepositoryV1',
+                'serviceVersion' => 'V1',
+                'operation' => 'eavAttributeSetRepositoryV1GetList',
+            ],
+        ];
+
+        $response = $this->_webApiCall($serviceInfo, $searchCriteria);
+
+        $this->assertArrayHasKey('search_criteria', $response);
+        $this->assertArrayHasKey('total_count', $response);
+        $this->assertArrayHasKey('items', $response);
+
+        $this->assertEquals($searchCriteria['searchCriteria'], $response['search_criteria']);
+        $this->assertTrue($response['total_count'] > 0);
+        $this->assertTrue(count($response['items']) > 0);
+
+        $this->assertNotNull($response['items'][0]['attribute_set_id']);
+        $this->assertNotNull($response['items'][0]['attribute_set_name']);
+    }
+
+    /**
+     * Retrieve attribute set based on given name.
+     * This utility methods assumes that there is only one attribute set with given name,
+     *
+     * @param string $attributeSetName
+     * @return \Magento\Eav\Model\Entity\Attribute\Set|null
+     */
+    protected function getAttributeSetByName($attributeSetName)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
+        $attributeSet = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Set')
+            ->load($attributeSetName, 'attribute_set_name');
+        if ($attributeSet->getId() === null) {
+            return null;
+        }
+        return $attributeSet;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Framework/Stdlib/CookieManagerTest.php b/dev/tests/api-functional/testsuite/Magento/Framework/Stdlib/CookieManagerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c90fcc223e698969319726ab87c9dec637e00d8
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Framework/Stdlib/CookieManagerTest.php
@@ -0,0 +1,164 @@
+<?php
+namespace Magento\Framework\Stdlib;
+
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\Webapi\Curl;
+
+/**
+ * End to end test of the Cookie Manager, using curl.
+ *
+ * Uses controllers in TestModule1 to set and delete cookies and verify 'Set-Cookie' headers that come back.
+ */
+class CookieManagerTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    private $cookieTesterUrl = 'testmoduleone/CookieTester';
+
+    /** @var Curl */
+    protected $curlClient;
+
+    public function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->config = $objectManager->get('Magento\Webapi\Model\Config');
+        $this->curlClient = $objectManager->get('Magento\TestFramework\TestCase\Webapi\Curl');
+    }
+
+    /**
+     * Set a sensitive Cookie and delete it.
+     *
+     */
+    public function testSensitiveCookie()
+    {
+        $url = $this->cookieTesterUrl . '/SetSensitiveCookie';
+        $cookieParams =
+            [
+                'cookie_name' => 'test-sensitive-cookie',
+                'cookie_value' => 'test-sensitive-cookie-value',
+            ];
+        $response = $this->curlClient->get($url, $cookieParams);
+
+        $cookie = $this->findCookie($cookieParams['cookie_name'], $response['cookies']);
+        $this->assertNotNull($cookie);
+        $this->assertEquals($cookieParams['cookie_name'], $cookie['name']);
+        $this->assertEquals($cookieParams['cookie_value'], $cookie['value']);
+        $this->assertFalse(isset($cookie['domain']));
+        $this->assertFalse(isset($cookie['path']));
+        $this->assertEquals('true', $cookie['httponly']);
+        $this->assertFalse(isset($cookie['secure']));
+        $this->assertFalse(isset($cookie['max-age']));
+    }
+
+    /**
+     * Set a public cookie
+     *
+     */
+    public function testPublicCookieNameValue()
+    {
+        $url = $this->cookieTesterUrl . '/SetPublicCookie';
+        $cookieParams =
+            [
+                'cookie_name' => 'test-cookie',
+                'cookie_value' => 'test-cookie-value',
+            ];
+
+        $response = $this->curlClient->get($url, $cookieParams);
+
+        $cookie = $this->findCookie($cookieParams['cookie_name'], $response['cookies']);
+        $this->assertNotNull($cookie);
+        $this->assertEquals($cookieParams['cookie_name'], $cookie['name']);
+        $this->assertEquals($cookieParams['cookie_value'], $cookie['value']);
+        $this->assertFalse(isset($cookie['domain']));
+        $this->assertFalse(isset($cookie['path']));
+        $this->assertFalse(isset($cookie['httponly']));
+        $this->assertFalse(isset($cookie['secure']));
+        $this->assertFalse(isset($cookie['max-age']));
+    }
+
+    /**
+     * Set a public cookie
+     *
+     */
+    public function testPublicCookieAll()
+    {
+        $url = $this->cookieTesterUrl . '/SetPublicCookie';
+        $cookieParams =
+            [
+                'cookie_name' => 'test-cookie',
+                'cookie_value' => 'test-cookie-value',
+                'cookie_domain' => 'www.example.com',
+                'cookie_path' => '/test/path',
+                'cookie_httponly' => 'true',
+                'cookie_secure' => 'true',
+                'cookie_duration' => '600',
+            ];
+
+        $response = $this->curlClient->get($url, $cookieParams);
+
+        $cookie = $this->findCookie($cookieParams['cookie_name'], $response['cookies']);
+        $this->assertNotNull($cookie);
+        $this->assertEquals($cookieParams['cookie_name'], $cookie['name']);
+        $this->assertEquals($cookieParams['cookie_value'], $cookie['value']);
+        $this->assertEquals($cookieParams['cookie_domain'], $cookie['domain']);
+        $this->assertEquals($cookieParams['cookie_path'], $cookie['path']);
+        $this->assertEquals($cookieParams['cookie_httponly'], $cookie['httponly']);
+        $this->assertEquals($cookieParams['cookie_secure'], $cookie['secure']);
+        if (isset($cookie['max-age'])) {
+            $this->assertEquals($cookieParams['cookie_duration'], $cookie['max-age']);
+        }
+        $this->assertTrue(isset($cookie['expires']));
+    }
+
+    /**
+     * Delete a cookie
+     *
+     */
+    public function testDeleteCookie()
+    {
+        $url = $this->cookieTesterUrl . '/DeleteCookie';
+        $cookieParams =
+            [
+                'cookie_name' => 'test-cookie',
+                'cookie_value' => 'test-cookie-value',
+            ];
+
+        $response = $this->curlClient->get(
+            $url,
+            $cookieParams,
+            ['Cookie: test-cookie=test-cookie-value; anothertestcookie=anothertestcookievalue']
+        );
+
+        $cookie = $this->findCookie($cookieParams['cookie_name'], $response['cookies']);
+        $this->assertNotNull($cookie);
+        $this->assertEquals($cookieParams['cookie_name'], $cookie['name']);
+        $this->assertEquals('deleted', $cookie['value']);
+        $this->assertFalse(isset($cookie['domain']));
+        $this->assertFalse(isset($cookie['path']));
+        $this->assertFalse(isset($cookie['httponly']));
+        $this->assertFalse(isset($cookie['secure']));
+        if (isset($cookie['max-age'])) {
+            $this->assertEquals(0, $cookie['max-age']);
+        }
+        $this->assertEquals('Thu, 01-Jan-1970 00:00:01 GMT', $cookie['expires']);
+    }
+
+    /**
+     * Find cookie with given name in the list of cookies
+     *
+     * @param string $cookieName
+     * @param array $cookies
+     * @return $cookie|null
+     */
+    private function findCookie($cookieName, $cookies)
+    {
+        foreach ($cookies as $cookieIndex => $cookie) {
+            if ($cookie['name'] === $cookieName) {
+                return $cookie;
+            }
+        }
+        return null;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/ReadServiceTest.php b/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/ReadServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a287d6c8e5106cac474a9a80492f1c02808f4aeb
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/ReadServiceTest.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\GiftMessage\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ReadServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'giftMessageReadServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/GiftMessage/_files/quote_with_message.php
+     */
+    public function testGet()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('message_order_21', 'reserved_order_id');
+
+        $cartId = $quote->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/gift-message',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $expectedMessage = [
+            'recipient' => 'Mercutio',
+            'sender' => 'Romeo',
+            'message' => 'I thought all for the best.',
+        ];
+
+        $requestData = ["cartId" => $cartId];
+        $resultMessage = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertCount(5, $resultMessage);
+        unset($resultMessage['gift_message_id']);
+        unset($resultMessage['customer_id']);
+        $this->assertEquals($expectedMessage, $resultMessage);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/GiftMessage/_files/quote_with_item_message.php
+     */
+    public function testGetItemMessage()
+    {
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_message', 'reserved_order_id');
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $product->load($product->getIdBySku('simple_with_message'));
+        $itemId = $quote->getItemByProduct($product)->getId();
+        /** @var  \Magento\Catalog\Model\Product $product */
+        $cartId = $quote->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/gift-message/' . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getItemMessage',
+            ],
+        ];
+
+        $expectedMessage = [
+            'recipient' => 'Jane Roe',
+            'sender' => 'John Doe',
+            'message' => 'Gift Message Text',
+        ];
+
+        $requestData = ["cartId" => $cartId, "itemId" => $itemId];
+        $resultMessage = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertCount(5, $resultMessage);
+        unset($resultMessage['gift_message_id']);
+        unset($resultMessage['customer_id']);
+        $this->assertEquals($expectedMessage, $resultMessage);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/WriteServiceTest.php b/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/WriteServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..79185a68dca2b8618eaaa3e04e33ee82781f82e1
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GiftMessage/Service/V1/WriteServiceTest.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\GiftMessage\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class WriteServiceTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+    const SERVICE_NAME = 'giftMessageWriteServiceV1';
+    const RESOURCE_PATH = '/V1/carts/';
+
+    /**
+     * @var \Magento\TestFramework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/GiftMessage/_files/quote_with_item_message.php
+     */
+    public function testSetForQuote()
+    {
+        // sales/gift_options/allow_order must be set to 1 in system configuration
+        // @todo remove next statement when \Magento\TestFramework\TestCase\WebapiAbstract::_updateAppConfig is fixed
+        $this->markTestIncomplete('This test relies on system configuration state.');
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_message', 'reserved_order_id');
+
+        $cartId = $quote->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/gift-message',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetForQuote',
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'giftMessage' => [
+                'recipient' => 'John Doe',
+                'sender' => 'Jane Roe',
+                'message' => 'Gift Message Text New',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+        $quote->load('test_order_item_with_message', 'reserved_order_id');
+        $quote->getGiftMessageId();
+        /** @var  \Magento\GiftMessage\Model\Message $message */
+        $message = $this->objectManager->create('Magento\GiftMessage\Model\Message')->load($quote->getGiftMessageId());
+        $this->assertEquals('John Doe', $message->getRecipient());
+        $this->assertEquals('Jane Roe', $message->getSender());
+        $this->assertEquals('Gift Message Text New', $message->getMessage());
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/GiftMessage/_files/quote_with_item_message.php
+     */
+    public function testSetForItem()
+    {
+        // sales/gift_options/allow_items must be set to 1 in system configuration
+        // @todo remove next statement when \Magento\TestFramework\TestCase\WebapiAbstract::_updateAppConfig is fixed
+        $this->markTestIncomplete('This test relies on system configuration state.');
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->load('test_order_item_with_message', 'reserved_order_id');
+        $cartId = $quote->getId();
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product');
+        $product->load($product->getIdBySku('simple_with_message'));
+        $itemId = $quote->getItemByProduct($product)->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $cartId . '/gift-message/' .  $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'SetForItem',
+            ],
+        ];
+
+        $requestData = [
+            'cartId' => $cartId,
+            'itemId' => $itemId,
+            'giftMessage' => [
+                'recipient' => 'John Doe',
+                'sender' => 'Jane Roe',
+                'message' => 'Gift Message Text New',
+            ],
+        ];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+//        $quote->load('test_order_item_with_message', 'reserved_order_id');
+        $messageId = $quote->getItemByProduct($product)->getGiftMessageId();
+        /** @var  \Magento\GiftMessage\Model\Message $message */
+        $message = $this->objectManager->create('Magento\GiftMessage\Model\Message')->load($messageId);
+        $this->assertEquals('John Doe', $message->getRecipient());
+        $this->assertEquals('Jane Roe', $message->getSender());
+        $this->assertEquals('Gift Message Text New', $message->getMessage());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a6ce3ac19f6f397cc24757950279022163d075e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\GroupedProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductLinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkManagementV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @magentoApiDataFixture Magento/GroupedProduct/_files/product_grouped.php
+     */
+    public function testGetLinkedItemsByType()
+    {
+        $productSku = 'grouped-product';
+        $linkType = 'associated';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetLinkedItemsByType',
+            ],
+        ];
+
+        $actual = $this->_webApiCall($serviceInfo, ['productSku' => $productSku, 'type' => $linkType]);
+
+        $expected = [
+            [
+                'product_sku' => 'grouped-product',
+                'link_type' => 'associated',
+                'linked_product_sku' => 'simple-1',
+                'linked_product_type' => 'simple',
+                'position' => 1,
+            ],
+            [
+                'product_sku' => 'grouped-product',
+                'link_type' => 'associated',
+                'linked_product_sku' => 'virtual-product',
+                'linked_product_type' => 'virtual',
+                'position' => 2,
+            ],
+        ];
+
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            array_walk(
+                $expected,
+                function (&$item) {
+                    $item['custom_attributes'] = [['attribute_code' => 'qty', 'value' => 1.0000]];
+                }
+            );
+        } else {
+            array_walk(
+                $expected,
+                function (&$item) {
+                    $item['custom_attributes'] = [['attribute_code' => 'qty', 'value' => 1.0000]];
+                }
+            );
+        }
+        $this->assertEquals($expected, $actual);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..80e1ca7370759d0df8adc3aaf2a5defd3b7cc6f6
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\GroupedProduct\Api;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+use Magento\TestFramework\Helper\Bootstrap;
+
+class ProductLinkRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+    /**
+     * @magentoApiDataFixture Magento/Catalog/_files/products_new.php
+     * @magentoApiDataFixture Magento/GroupedProduct/_files/product_grouped.php
+     */
+    public function testSave()
+    {
+        $productSku = 'grouped-product';
+        $linkType = 'associated';
+        $productData = [
+            'product_sku' => $productSku,
+            'link_type' => $linkType,
+            'linked_product_type' => 'simple',
+            'linked_product_sku' => 'simple',
+            'position' => 3,
+            'custom_attributes' => [
+                'qty' => ['attribute_code' => 'qty', 'value' => (float) 300.0000],
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, ['entity' => $productData]);
+
+        /** @var \Magento\Catalog\Model\ProductLink\Management $linkManagement */
+        $linkManagement = $this->objectManager->get('Magento\Catalog\Api\ProductLinkManagementInterface');
+        $actual = $linkManagement->getLinkedItemsByType($productSku, $linkType);
+        array_walk($actual, function (&$item) {
+            $item = $item->__toArray();
+        });
+        $this->assertEquals($productData, $actual[2]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkTypeListTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkTypeListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cec4ba0b6777c74ba37ec0aade980d18bcae2933
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkTypeListTest.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\GroupedProduct\Api;
+
+use Magento\GroupedProduct\Model\Resource\Product\Link;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ProductLinkTypeListTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    const SERVICE_NAME = 'catalogProductLinkTypeListV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/products/';
+
+    public function testGetItems()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . 'links/types',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetItems',
+            ],
+        ];
+
+        $actual = $this->_webApiCall($serviceInfo);
+
+        /**
+         * Validate that product type links provided by Magento_GroupedProduct module are present
+         */
+        $expectedItems = ['name' => 'associated', 'code' => Link::LINK_TYPE_GROUPED];
+        $this->assertContains($expectedItems, $actual);
+    }
+
+    public function testGetItemAttributes()
+    {
+        $linkType = 'associated';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . 'links/' . $linkType . '/attributes',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetItemAttributes',
+            ],
+        ];
+
+        $actual = $this->_webApiCall($serviceInfo, ['type' => $linkType]);
+
+        $expected = [
+            ['code' => 'position', 'type' => 'int'],
+            ['code' => 'qty', 'type' => 'decimal'],
+        ];
+        $this->assertEquals($expected, $actual);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..91e6a4cad97841feb4c1d2d91c61a97bd7dfa2cd
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Integration\Service\V1;
+
+use Magento\Framework\Exception\InputException;
+use Magento\Integration\Model\Oauth\Token as TokenModel;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\User\Model\User as UserModel;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+
+/**
+ * api-functional test for \Magento\Integration\Service\V1\AdminTokenService.
+ */
+class AdminTokenServiceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "integrationAdminTokenServiceV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH_ADMIN_TOKEN = "/V1/integration/admin/token";
+    const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
+
+    /**
+     * @var AdminTokenServiceInterface
+     */
+    private $tokenService;
+
+    /**
+     * @var TokenModel
+     */
+    private $tokenModel;
+
+    /**
+     * @var UserModel
+     */
+    private $userModel;
+
+    /**
+     * Setup AdminTokenService
+     */
+    public function setUp()
+    {
+        $this->_markTestAsRestOnly();
+        $this->tokenService = Bootstrap::getObjectManager()->get('Magento\Integration\Service\V1\AdminTokenService');
+        $this->tokenModel = Bootstrap::getObjectManager()->get('Magento\Integration\Model\Oauth\Token');
+        $this->userModel = Bootstrap::getObjectManager()->get('Magento\User\Model\User');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/User/_files/user_with_role.php
+     */
+    public function testCreateAdminAccessToken()
+    {
+        $adminUserNameFromFixture = 'adminUser';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_ADMIN_TOKEN,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+        $requestData = [
+            'username' => $adminUserNameFromFixture,
+            'password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
+        ];
+        $accessToken = $this->_webApiCall($serviceInfo, $requestData);
+
+        $adminUserId = $this->userModel->loadByUsername($adminUserNameFromFixture)->getId();
+        /** @var $token TokenModel */
+        $token = $this->tokenModel
+            ->loadByAdminId($adminUserId)
+            ->getToken();
+        $this->assertEquals($accessToken, $token);
+    }
+
+    /**
+     * @dataProvider validationDataProvider
+     */
+    public function testCreateAdminAccessTokenEmptyOrNullCredentials()
+    {
+        try {
+            $serviceInfo = [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH_ADMIN_TOKEN,
+                    'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+                ],
+            ];
+            $requestData = ['username' => '', 'password' => ''];
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $this->assertInputExceptionMessages($e);
+        }
+    }
+
+    public function testCreateAdminAccessTokenInvalidCustomer()
+    {
+        $customerUserName = 'invalid';
+        $password = 'invalid';
+        try {
+            $serviceInfo = [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
+                    'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+                ],
+            ];
+            $requestData = ['username' => $customerUserName, 'password' => $password];
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode());
+            $exceptionData = $this->processRestExceptionResult($e);
+            $expectedExceptionData = ['message' => 'Invalid login or password.'];
+        }
+        $this->assertEquals($expectedExceptionData, $exceptionData);
+    }
+
+    /**
+     * Provider to test input validation
+     *
+     * @return array
+     */
+    public function validationDataProvider()
+    {
+        return [
+            'Check for empty credentials' => ['', ''],
+            'Check for null credentials' => [null, null]
+        ];
+    }
+
+    /**
+     * Assert for presence of Input exception messages
+     *
+     * @param \Exception $e
+     */
+    private function assertInputExceptionMessages($e)
+    {
+        $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        $exceptionData = $this->processRestExceptionResult($e);
+        $expectedExceptionData = [
+            'message' => InputException::DEFAULT_MESSAGE,
+            'errors' => [
+                [
+                    'message' => InputException::REQUIRED_FIELD,
+                    'parameters' => [
+                        'fieldName' => 'username',
+                    ],
+                ],
+                [
+                    'message' => InputException::REQUIRED_FIELD,
+                    'parameters' => [
+                        'fieldName' => 'password',
+                    ]
+                ],
+            ],
+        ];
+        $this->assertEquals($expectedExceptionData, $exceptionData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php b/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6a4f4f2ce28bbcbf002beb7a2af25c70d51eb88
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php
@@ -0,0 +1,164 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Integration\Service\V1;
+
+use Magento\Customer\Api\AccountManagementInterface;
+use Magento\Framework\Exception\InputException;
+use Magento\Integration\Model\Oauth\Token as TokenModel;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\User\Model\User as UserModel;
+use Magento\Webapi\Exception as HTTPExceptionCodes;
+
+/**
+ * api-functional test for \Magento\Integration\Service\V1\CustomerTokenService.
+ */
+class CustomerTokenServiceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "integrationCustomerTokenServiceV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
+    const RESOURCE_PATH_ADMIN_TOKEN = "/V1/integration/admin/token";
+
+    /**
+     * @var CustomerTokenServiceInterface
+     */
+    private $tokenService;
+
+    /**
+     * @var AccountManagementInterface
+     */
+    private $customerAccountManagement;
+
+    /**
+     * @var TokenModel
+     */
+    private $tokenModel;
+
+    /**
+     * @var UserModel
+     */
+    private $userModel;
+
+    /**
+     * Setup CustomerTokenService
+     */
+    public function setUp()
+    {
+        $this->_markTestAsRestOnly();
+        $this->tokenService = Bootstrap::getObjectManager()->get('Magento\Integration\Service\V1\CustomerTokenService');
+        $this->customerAccountManagement = Bootstrap::getObjectManager()->get(
+            'Magento\Customer\Api\AccountManagementInterface'
+        );
+        $this->tokenModel = Bootstrap::getObjectManager()->get('Magento\Integration\Model\Oauth\Token');
+        $this->userModel = Bootstrap::getObjectManager()->get('Magento\User\Model\User');
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Customer/_files/customer.php
+     */
+    public function testCreateCustomerAccessToken()
+    {
+        $customerUserName = 'customer@example.com';
+        $password = 'password';
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+        $requestData = ['username' => $customerUserName, 'password' => $password];
+        $accessToken = $this->_webApiCall($serviceInfo, $requestData);
+
+        $customerData = $this->customerAccountManagement->authenticate($customerUserName, $password);
+        /** @var $token TokenModel */
+        $token = $this->tokenModel->loadByCustomerId($customerData->getId())->getToken();
+        $this->assertEquals($accessToken, $token);
+    }
+
+    /**
+     * @dataProvider validationDataProvider
+     */
+    public function testCreateCustomerAccessTokenEmptyOrNullCredentials($username, $password)
+    {
+        try {
+            $serviceInfo = [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
+                    'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+                ],
+            ];
+            $requestData = ['username' => '', 'password' => ''];
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $this->assertInputExceptionMessages($e);
+        }
+    }
+
+    public function testCreateCustomerAccessTokenInvalidCustomer()
+    {
+        $customerUserName = 'invalid';
+        $password = 'invalid';
+        try {
+            $serviceInfo = [
+                'rest' => [
+                    'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
+                    'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+                ],
+            ];
+            $requestData = ['username' => $customerUserName, 'password' => $password];
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode());
+            $exceptionData = $this->processRestExceptionResult($e);
+            $expectedExceptionData = ['message' => 'Invalid login or password.'];
+        }
+        $this->assertEquals($expectedExceptionData, $exceptionData);
+    }
+
+    /**
+     * Provider to test input validation
+     *
+     * @return array
+     */
+    public function validationDataProvider()
+    {
+        return [
+            'Check for empty credentials' => ['', ''],
+            'Check for null credentials' => [null, null]
+        ];
+    }
+
+    /**
+     * Assert for presence of Input exception messages
+     *
+     * @param \Exception $e
+     */
+    private function assertInputExceptionMessages($e)
+    {
+        $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
+        $exceptionData = $this->processRestExceptionResult($e);
+        $expectedExceptionData = [
+            'message' => InputException::DEFAULT_MESSAGE,
+            'errors' => [
+                [
+                    'message' => InputException::REQUIRED_FIELD,
+                    'parameters' => [
+                        'fieldName' => 'username',
+                    ],
+                ],
+                [
+                    'message' => InputException::REQUIRED_FIELD,
+                    'parameters' => [
+                        'fieldName' => 'password',
+                    ]
+                ],
+            ],
+        ];
+        $this->assertEquals($expectedExceptionData, $exceptionData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoAddCommentTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoAddCommentTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..885bcb8f8b717e5063748b2c2d4cbf229c6c56aa
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoAddCommentTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\CreditmemoCommentInterface as Comment;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class CreditmemoAddCommentTest
+ */
+class CreditmemoAddCommentTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesCreditmemoCommentRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Creditmemo increment id
+     */
+    const CREDITMEMO_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test creditmemo add comment service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_with_list.php
+     */
+    public function testCreditmemoAddComment()
+    {
+        /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */
+        $creditmemoCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Creditmemo\Collection');
+        $creditmemo = $creditmemoCollection->getFirstItem();
+
+        $commentData = [
+            Comment::COMMENT => 'Hello world!',
+            Comment::ENTITY_ID => null,
+            Comment::CREATED_AT => null,
+            Comment::PARENT_ID => $creditmemo->getId(),
+            Comment::IS_VISIBLE_ON_FRONT => true,
+            Comment::IS_CUSTOMER_NOTIFIED => true,
+        ];
+
+        $requestData = ['entity' => $commentData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/creditmemo/comment',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7ad70a57658f0c358b67f6d532b12e130e56d28
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class CreditmemoCancelTest
+ */
+class CreditmemoCancelTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesCreditmemoManagementV1';
+
+    const CREDITMEMO_INCREMENT_ID = '100000001';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_with_list.php
+     */
+    public function testCreditmemoCancel()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */
+        $creditmemoCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Creditmemo\Collection');
+        $creditmemo = $creditmemoCollection->getFirstItem();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/creditmemo/' . $creditmemo->getId(),
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'cancel',
+            ],
+        ];
+        $requestData = ['id' => $creditmemo->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCommentsListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCommentsListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2566256747465ca80f3dcfa3f5f203675502e3d5
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCommentsListTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\CreditmemoCommentInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class CreditmemoCommentsListTest
+ */
+class CreditmemoCommentsListTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'salesCreditmemoManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_for_get.php
+     */
+    public function testCreditmemoCommentsList()
+    {
+        $comment = 'Test comment';
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */
+        $creditmemoCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Creditmemo\Collection');
+        $creditmemo = $creditmemoCollection->getFirstItem();
+        $creditmemoComment = $objectManager->get('Magento\Sales\Model\Order\Creditmemo\Comment');
+
+        $commentData = [
+            CreditmemoCommentInterface::COMMENT => 'Hello world!',
+            CreditmemoCommentInterface::ENTITY_ID => null,
+            CreditmemoCommentInterface::CREATED_AT => null,
+            CreditmemoCommentInterface::PARENT_ID => $creditmemo->getId(),
+            CreditmemoCommentInterface::IS_VISIBLE_ON_FRONT => true,
+            CreditmemoCommentInterface::IS_CUSTOMER_NOTIFIED => true,
+        ];
+        $creditmemoComment->setData($commentData)->save();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/creditmemo/' . $creditmemo->getId() . '/comments',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getCommentsList',
+            ],
+        ];
+        $requestData = ['id' => $creditmemo->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        $this->assertNotEmpty($result);
+        foreach ($result['items'] as $item) {
+            $comment = $objectManager->get('Magento\Sales\Model\Order\Creditmemo\Comment')->load($item['entity_id']);
+            $this->assertEquals($comment->getComment(), $item['comment']);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7fb134e9d20243d6e04bdd75f7f47768336973f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class CreditmemoCreateTest
+ */
+class CreditmemoCreateTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/creditmemo';
+
+    const SERVICE_READ_NAME = 'salesCreditmemoRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoke()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $orderCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Collection');
+        $order = $orderCollection->getFirstItem();
+
+//        $order = $this->objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        /** @var \Magento\Sales\Model\Order\Item $orderItem */
+        $orderItem = current($order->getAllItems());
+        $items = [
+            $orderItem->getId() => ['qty' => $orderItem->getQtyInvoiced(), 'order_item_id' => $orderItem->getId()],
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+        $data = [
+            'adjustment' => null,
+            'adjustment_negative' => null,
+            'adjustment_positive' => null,
+            'base_adjustment' => null,
+            'base_adjustment_negative' => null,
+            'base_adjustment_positive' => null,
+            'base_currency_code' => null,
+            'base_discount_amount' => null,
+            'base_grand_total' => null,
+            'base_hidden_tax_amount' => null,
+            'base_shipping_amount' => null,
+            'base_shipping_hidden_tax_amnt' => null,
+            'base_shipping_incl_tax' => null,
+            'base_shipping_tax_amount' => null,
+            'base_subtotal' => null,
+            'base_subtotal_incl_tax' => null,
+            'base_tax_amount' => null,
+            'base_to_global_rate' => null,
+            'base_to_order_rate' => null,
+            'billing_address_id' => null,
+            'created_at' => null,
+            'creditmemo_status' => null,
+            'discount_amount' => null,
+            'discount_description' => null,
+            'email_sent' => null,
+            'entity_id' => null,
+            'global_currency_code' => null,
+            'grand_total' => null,
+            'hidden_tax_amount' => null,
+            'increment_id' => null,
+            'invoice_id' => null,
+            'order_currency_code' => null,
+            'order_id' => $order->getId(),
+            'shipping_address_id' => null,
+            'shipping_amount' => null,
+            'shipping_hidden_tax_amount' => null,
+            'shipping_incl_tax' => null,
+            'shipping_tax_amount' => null,
+            'state' => null,
+            'store_currency_code' => null,
+            'store_id' => null,
+            'store_to_base_rate' => null,
+            'store_to_order_rate' => null,
+            'subtotal' => null,
+            'subtotal_incl_tax' => null,
+            'tax_amount' => null,
+            'transaction_id' => null,
+            'updated_at' => null,
+            'items' => $items,
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['entity' => $data]);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..828a0338c3669a7fab59d96d3dab1091f053fdc5
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class CreditmemoEmailTest
+ */
+class CreditmemoEmailTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesCreditmemoManagementV1';
+
+    const CREDITMEMO_INCREMENT_ID = '100000001';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_with_list.php
+     */
+    public function testCreditmemoEmail()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */
+        $creditmemoCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Creditmemo\Collection');
+        $creditmemo = $creditmemoCollection->getFirstItem();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/creditmemo/' . $creditmemo->getId(),
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'notify',
+            ],
+        ];
+        $requestData = ['id' => $creditmemo->getId()];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoGetTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoGetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e11ef7791c2c70bf02800040c6c7012f6690b35
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoGetTest.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class CreditmemoGetTest
+ */
+class CreditmemoGetTest extends WebapiAbstract
+{
+    /**
+     * Resource path
+     */
+    const RESOURCE_PATH = '/V1/creditmemo';
+
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesCreditmemoRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Creditmemo id
+     */
+    const CREDITMEMO_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * Required fields are in the answer
+     *
+     * @var array
+     */
+    protected $requiredFields = [
+        'entity_id',
+        'store_id',
+        'base_shipping_tax_amount',
+        'base_discount_amount',
+        'grand_total',
+        'base_subtotal_incl_tax',
+        'shipping_amount',
+        'subtotal_incl_tax',
+        'base_shipping_amount',
+        'base_adjustment',
+        'base_subtotal',
+        'discount_amount',
+        'subtotal',
+        'adjustment',
+        'base_grand_total',
+        'base_tax_amount',
+        'shipping_tax_amount',
+        'tax_amount',
+        'order_id',
+        'state',
+        'increment_id',
+    ];
+
+    /**
+     * Set up
+     */
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test creditmemo get service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_for_get.php
+     */
+    public function testCreditmemoGet()
+    {
+        /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */
+        $creditmemoCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Creditmemo\Collection');
+        $creditmemo = $creditmemoCollection->getFirstItem();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $creditmemo->getId(),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'get',
+            ],
+        ];
+
+        $actual = $this->_webApiCall($serviceInfo, ['id' => $creditmemo->getId()]);
+        $expected = $creditmemo->getData();
+
+        foreach ($this->requiredFields as $field) {
+            $this->assertArrayHasKey($field, $actual);
+            $this->assertEquals($expected[$field], $actual[$field]);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3b4dd59b1c3aa67bd9a95791454e1f679f0f091
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class CreditmemoListTest
+ */
+class CreditmemoListTest extends WebapiAbstract
+{
+    /**
+     * Resource path
+     */
+    const RESOURCE_PATH = '/V1/creditmemos';
+
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesCreditmemoRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    /**
+     * Set up
+     */
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test creditmemo list service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/creditmemo_with_list.php
+     */
+    public function testCreditmemoList()
+    {
+        /** @var $searchCriteriaBuilder  \Magento\Framework\Api\SearchCriteriaBuilder */
+        $searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+
+        /** @var $filterBuilder  \Magento\Framework\Api\FilterBuilder */
+        $filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        $searchCriteriaBuilder->addFilter(
+            [
+                $filterBuilder
+                    ->setField('state')
+                    ->setValue(\Magento\Sales\Model\Order\Creditmemo::STATE_OPEN)
+                    ->create(),
+            ]
+        );
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+
+        $requestData = ['criteria' => $searchData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getList',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        $this->assertArrayHasKey('items', $result);
+        $this->assertCount(1, $result['items']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceAddCommentTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceAddCommentTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d76ae8a2778065ca05e41abfeb374751362bb1b1
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceAddCommentTest.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\InvoiceCommentInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class InvoiceAddCommentTest
+ */
+class InvoiceAddCommentTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesInvoiceCommentRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Test invoice add comment service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoiceAddComment()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order\Invoice $invoice */
+        $invoiceCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Invoice\Collection');
+        $invoice = $invoiceCollection->getFirstItem();
+
+        $commentData = [
+            InvoiceCommentInterface::COMMENT => 'Hello world!',
+            InvoiceCommentInterface::ENTITY_ID => null,
+            InvoiceCommentInterface::CREATED_AT => null,
+            InvoiceCommentInterface::PARENT_ID => $invoice->getId(),
+            InvoiceCommentInterface::IS_VISIBLE_ON_FRONT => true,
+            InvoiceCommentInterface::IS_CUSTOMER_NOTIFIED => true,
+        ];
+
+        $requestData = ['entity' => $commentData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/invoice/comment',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCaptureTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCaptureTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca013830487ef16025c181088bdb332deb2d341d
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCaptureTest.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class InvoiceCaptureTest
+ */
+class InvoiceCaptureTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesInvoiceManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     * @expectedException \Exception
+     */
+    public function testInvoiceCapture()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order\Invoice $invoice */
+        $invoice = $objectManager->get('Magento\Sales\Model\Order\Invoice')->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/invoices/' . $invoice->getId() . '/capture',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'setCapture',
+            ],
+        ];
+        $requestData = ['id' => $invoice->getId()];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCommentsListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCommentsListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c5d7a5f343763f7b936202216113d6a4fffd523
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCommentsListTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class InvoiceCommentsListTest
+ */
+class InvoiceCommentsListTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'salesInvoiceManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoiceCommentsList()
+    {
+        $comment = 'Test comment';
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var \Magento\Sales\Model\Resource\Order\Invoice\Collection $invoiceCollection */
+        $invoiceCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Invoice\Collection');
+        $invoice = $invoiceCollection->getFirstItem();
+        $invoiceComment = $objectManager->get('Magento\Sales\Model\Order\Invoice\Comment');
+        $invoiceComment->setComment($comment);
+        $invoiceComment->setParentId($invoice->getId());
+        $invoiceComment->save();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/invoice/' . $invoice->getId() . '/comments',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getCommentsList',
+            ],
+        ];
+        $requestData = ['id' => $invoice->getId()];
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        foreach ($result['items'] as $item) {
+            /** @var \Magento\Sales\Model\Order\Invoice\Comment $invoiceHistoryStatus */
+            $invoiceHistoryStatus = $objectManager->get('Magento\Sales\Model\Order\Invoice\Comment')
+                ->load($item['entity_id']);
+            $this->assertEquals($invoiceHistoryStatus->getComment(), $item['comment']);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc5600ccfa72e13126eb8608c06bafdcfbbcaa9e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class InvoiceCreateTest
+ */
+class InvoiceCreateTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/invoice';
+
+    const SERVICE_READ_NAME = 'salesInvoiceRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testInvoke()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+        $orderItems = $order->getAllItems();
+        $data = [
+            'order_id' => $order->getId(),
+            'base_currency_code' => null,
+            'base_discount_amount' => null,
+            'base_grand_total' => null,
+            'base_hidden_tax_amount' => null,
+            'base_shipping_amount' => null,
+            'base_shipping_hidden_tax_amnt' => null,
+            'base_shipping_incl_tax' => null,
+            'base_shipping_tax_amount' => null,
+            'base_subtotal' => null,
+            'base_subtotal_incl_tax' => null,
+            'base_tax_amount' => null,
+            'base_total_refunded' => null,
+            'base_to_global_rate' => null,
+            'base_to_order_rate' => null,
+            'billing_address_id' => null,
+            'can_void_flag' => null,
+            'created_at' => null,
+            'discount_amount' => null,
+            'discount_description' => null,
+            'email_sent' => null,
+            'entity_id' => null,
+            'global_currency_code' => null,
+            'grand_total' => null,
+            'hidden_tax_amount' => null,
+            'increment_id' => null,
+            'is_used_for_refund' => null,
+            'order_currency_code' => null,
+            'shipping_address_id' => null,
+            'shipping_amount' => null,
+            'shipping_hidden_tax_amount' => null,
+            'shipping_incl_tax' => null,
+            'shipping_tax_amount' => null,
+            'state' => null,
+            'store_currency_code' => null,
+            'store_id' => null,
+            'store_to_base_rate' => null,
+            'store_to_order_rate' => null,
+            'subtotal' => null,
+            'subtotal_incl_tax' => null,
+            'tax_amount' => null,
+            'total_qty' => '1',
+            'transaction_id' => null,
+            'updated_at' => null,
+            'items' => [
+                [
+                    'orderItemId' => $orderItems[0]->getId(),
+                    'qty' => 2,
+                    'additionalData' => null,
+                    'baseCost' => null,
+                    'baseDiscountAmount' => null,
+                    'baseHiddenTaxAmount' => null,
+                    'basePrice' => null,
+                    'basePriceInclTax' => null,
+                    'baseRowTotal' => null,
+                    'baseRowTotalInclTax' => null,
+                    'baseTaxAmount' => null,
+                    'description' => null,
+                    'discountAmount' => null,
+                    'hiddenTaxAmount' => null,
+                    'name' => null,
+                    'entity_id' => null,
+                    'parentId' => null,
+                    'price' => null,
+                    'priceInclTax' => null,
+                    'productId' => null,
+                    'rowTotal' => null,
+                    'rowTotalInclTax' => null,
+                    'sku' => 'sku' . uniqid(),
+                    'taxAmount' => null,
+                ],
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['entity' => $data]);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceEmailTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceEmailTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..51ab88ff60a70ef4fe80ac2e044e0a31d62482c0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceEmailTest.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class InvoiceEmailTest
+ */
+class InvoiceEmailTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesInvoiceManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoiceEmail()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $invoiceCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Invoice\Collection');
+        $invoice = $invoiceCollection->getFirstItem();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/invoice/' . $invoice->getId() . '/email',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'notify',
+            ],
+        ];
+        $requestData = ['id' => $invoice->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceGetTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceGetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5de3f1ff0a5613431f7f9a158b684d343e4269b0
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceGetTest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class InvoiceGetTest
+ */
+class InvoiceGetTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/invoice';
+
+    const SERVICE_READ_NAME = 'salesInvoiceRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoiceGet()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order\Invoice $invoice */
+        $invoiceCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Invoice\Collection');
+        $invoice = $invoiceCollection->getFirstItem();
+        $expectedInvoiceData = [
+            'grand_total' => '100.0000',
+            'subtotal' => '100.0000',
+            'increment_id' => $invoice->getIncrementId(),
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $invoice->getId(),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'get',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['id' => $invoice->getId()]);
+        foreach ($expectedInvoiceData as $field => $value) {
+            $this->assertArrayHasKey($field, $result);
+            $this->assertEquals($value, $result[$field]);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea0565c64bb8827ddb81a3205ad9403080039b2e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class InvoiceListTest
+ */
+class InvoiceListTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/invoices';
+
+    const SERVICE_READ_NAME = 'salesInvoiceRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     */
+    public function testInvoiceList()
+    {
+        /** @var $searchCriteriaBuilder  \Magento\Framework\Api\SearchCriteriaBuilder */
+        $searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+
+        /** @var $filterBuilder  \Magento\Framework\Api\FilterBuilder */
+        $filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        $searchCriteriaBuilder->addFilter(
+            [
+                $filterBuilder
+                    ->setField('state')
+                    ->setValue(2)
+                    ->create(),
+            ]
+        );
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+
+        $requestData = ['criteria' => $searchData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getList',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        $this->assertArrayHasKey('items', $result);
+        $this->assertCount(1, $result['items']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceVoidTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceVoidTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..58fe16154eb46c0ffe815c40d09cec9e04dd8daa
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceVoidTest.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class InvoiceVoidTest
+ */
+class InvoiceVoidTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesInvoiceManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/invoice.php
+     * @expectedException \Exception
+     */
+    public function testInvoiceVoid()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order\Invoice $invoice */
+        $invoice = $objectManager->get('Magento\Sales\Model\Order\Invoice')->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/invoices/' . $invoice->getId() . '/void',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'setVoid',
+            ],
+        ];
+        $requestData = ['id' => $invoice->getId()];
+        $this->_webApiCall($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderAddressUpdateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderAddressUpdateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b99a39ca69e65eba98805151947b4518633ef3a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderAddressUpdateTest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\OrderAddressInterface as OrderAddress;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class OrderAddressUpdateTest
+ */
+class OrderAddressUpdateTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesOrderAddressRepositoryV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderAddressUpdate()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $objectManager->get('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+
+        $address = [
+            OrderAddress::REGION => 'CA',
+            OrderAddress::POSTCODE => '11111',
+            OrderAddress::LASTNAME => 'lastname',
+            OrderAddress::STREET => ['street'],
+            OrderAddress::CITY => 'city',
+            OrderAddress::EMAIL => 'email@email.com',
+            OrderAddress::COMPANY => 'company',
+            OrderAddress::TELEPHONE => 't123456789',
+            OrderAddress::COUNTRY_ID => 'US',
+            OrderAddress::FIRSTNAME => 'firstname',
+            OrderAddress::ADDRESS_TYPE => 'billing',
+            OrderAddress::PARENT_ID => $order->getId(),
+            OrderAddress::ENTITY_ID => $order->getBillingAddressId(),
+            OrderAddress::CUSTOMER_ADDRESS_ID => null,
+            OrderAddress::CUSTOMER_ID => null,
+            OrderAddress::FAX => null,
+            OrderAddress::MIDDLENAME => null,
+            OrderAddress::PREFIX => null,
+            OrderAddress::QUOTE_ADDRESS_ID => null,
+            OrderAddress::REGION_ID => null,
+            OrderAddress::SUFFIX => null,
+            OrderAddress::VAT_ID => null,
+            OrderAddress::VAT_IS_VALID => null,
+            OrderAddress::VAT_REQUEST_DATE => null,
+            OrderAddress::VAT_REQUEST_ID => null,
+            OrderAddress::VAT_REQUEST_SUCCESS => null,
+        ];
+        $requestData = ['entity' => $address];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId(),
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'save',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertGreaterThan(1, count($result));
+
+        /** @var \Magento\Sales\Model\Order $actualOrder */
+        $actualOrder = $objectManager->get('Magento\Sales\Model\Order')->load($order->getId());
+        $billingAddress = $actualOrder->getBillingAddress();
+
+        $validate = [
+            OrderAddress::REGION => 'CA',
+            OrderAddress::POSTCODE => '11111',
+            OrderAddress::LASTNAME => 'lastname',
+            OrderAddress::STREET => 'street',
+            OrderAddress::CITY => 'city',
+            OrderAddress::EMAIL => 'email@email.com',
+            OrderAddress::COMPANY => 'company',
+            OrderAddress::TELEPHONE => 't123456789',
+            OrderAddress::COUNTRY_ID => 'US',
+            OrderAddress::FIRSTNAME => 'firstname',
+            OrderAddress::ADDRESS_TYPE => 'billing',
+            OrderAddress::PARENT_ID => $order->getId(),
+            OrderAddress::ENTITY_ID => $order->getBillingAddressId(),
+        ];
+        foreach ($validate as $key => $field) {
+            $this->assertEquals($validate[$key], $billingAddress->getData($key));
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..39a1efd249f994ac443386cb2a06ba58b8fd379e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCancelTest.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class OrderCancelTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesOrderManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderCancel()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $order = $objectManager->get('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/cancel',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'cancel',
+            ],
+        ];
+        $requestData = ['id' => $order->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCommentsListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCommentsListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6137432d1634aa1fbdd4ec94869431b261d2ab6c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCommentsListTest.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class OrderCommentsListTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'salesOrderManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderCommentsList()
+    {
+        $comment = 'Test comment';
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $objectManager->get('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        $history = $order->addStatusHistoryComment($comment, $order->getStatus());
+        $history->save();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/comments',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getCommentsList',
+            ],
+        ];
+        $requestData = ['id' => $order->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        foreach ($result['items'] as $history) {
+            $orderHistoryStatus = $objectManager->get('Magento\Sales\Model\Order\Status\History')
+                ->load($history['entity_id']);
+            $this->assertEquals($orderHistoryStatus->getComment(), $history['comment']);
+            $this->assertEquals($orderHistoryStatus->getStatus(), $history['status']);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e7bd417de67b0830c41a8f81d38ba2a7254c574
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\OrderInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+class OrderCreateTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/order';
+
+    const SERVICE_READ_NAME = 'salesOrderRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    const ORDER_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    protected function prepareOrder()
+    {
+        /** @var \Magento\Sales\Model\Order $orderBuilder */
+        $orderFactory = $this->objectManager->get('Magento\Sales\Model\OrderFactory');
+        /** @var \Magento\Sales\Service\V1\Data\OrderItemBuilder $orderItemBuilder */
+        $orderItemFactory = $this->objectManager->get('Magento\Sales\Model\Order\ItemFactory');
+        /** @var \Magento\Sales\Service\V1\Data\OrderPaymentBuilder $orderPaymentBuilder */
+        $orderPaymentFactory = $this->objectManager->get('Magento\Sales\Model\Order\PaymentFactory');
+        /** @var \Magento\Sales\Service\V1\Data\OrderAddressBuilder $orderAddressBuilder */
+        $orderAddressFactory = $this->objectManager->get('Magento\Sales\Model\Order\AddressFactory');
+
+        $order = $orderFactory->create(
+            ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderInterface')]
+        );
+        $orderItem = $orderItemFactory->create(
+            ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderItemInterface')]
+        );
+        $orderPayment = $orderPaymentFactory->create(
+            ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderPaymentInterface')]
+        );
+        $orderAddressBilling = $orderAddressFactory->create(
+            ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderAddressInterface')]
+        );
+
+        $email = uniqid() . 'email@example.com';
+        $orderItem->setSku('sku#1');
+        $orderPayment->setCcLast4('4444');
+        $orderPayment->setMethod('checkmo');
+        $orderPayment->setAccountStatus('ok');
+        $orderPayment->setAdditionalInformation([]);
+        $order->setCustomerEmail($email);
+        $order->setBaseGrandTotal(100);
+        $order->setGrandTotal(100);
+        $order->setItems([$orderItem->getData()]);
+        $order->setPayments([$orderPayment->getData()]);
+        $orderAddressBilling->setCity('City');
+        $orderAddressBilling->setPostcode('12345');
+        $orderAddressBilling->setLastname('Last Name');
+        $orderAddressBilling->setFirstname('First Name');
+        $orderAddressBilling->setTelephone('+00(000)-123-45-57');
+        $orderAddressBilling->setStreet(['Street']);
+        $orderAddressBilling->setCountryId(1);
+        $orderAddressBilling->setAddressType('billing');
+
+        $orderAddressShipping = $orderAddressFactory->create(
+            ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderAddressInterface')]
+        );
+        $orderAddressShipping->setCity('City');
+        $orderAddressShipping->setPostcode('12345');
+        $orderAddressShipping->setLastname('Last Name');
+        $orderAddressShipping->setFirstname('First Name');
+        $orderAddressShipping->setTelephone('+00(000)-123-45-57');
+        $orderAddressShipping->setStreet(['Street']);
+        $orderAddressShipping->setCountryId(1);
+        $orderAddressShipping->setAddressType('shipping');
+
+        $orderData = $order->getData();
+        $orderData['billing_address'] = $orderAddressBilling->getData();
+        $orderData['billing_address']['street'] = ['Street'];
+        $orderData['shipping_address'] = $orderAddressShipping->getData();
+        $orderData['shipping_address']['street'] = ['Street'];
+        return $orderData;
+    }
+
+    protected function getDataStructure($className)
+    {
+        $refClass = new \ReflectionClass($className);
+        $constants = $refClass->getConstants();
+        $data = array_fill_keys($constants, null);
+        unset($data['custom_attributes']);
+        return $data;
+    }
+
+    public function testOrderCreate()
+    {
+        $order = $this->prepareOrder();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+        $this->assertNotEmpty($this->_webApiCall($serviceInfo, ['entity' => $order]));
+
+        /** @var \Magento\Sales\Model\Order $model */
+        $model = $this->objectManager->get('Magento\Sales\Model\Order');
+        $model->load($order['customer_email'], 'customer_email');
+        $this->assertTrue((bool)$model->getId());
+        $this->assertEquals($order['base_grand_total'], $model->getBaseGrandTotal());
+        $this->assertEquals($order['grand_total'], $model->getGrandTotal());
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderEmailTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderEmailTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3bdb00820ba4a8b0e04114158db4b0b1c08cb56d
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderEmailTest.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class OrderEmailTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesOrderManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderEmail()
+    {
+        $order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+            ->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/email',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'notify',
+            ],
+        ];
+        $requestData = ['id' => $order->getId()];
+        $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetStatusTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetStatusTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..97786a34970d133736c29c08e0651d67853f8b01
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetStatusTest.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class OrderGetStatusTest
+ * @package Magento\Sales\Service\V1
+ */
+class OrderGetStatusTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/order/%d/status';
+
+    const SERVICE_READ_NAME = 'salesOrderManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    const ORDER_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderGetStatus()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId(self::ORDER_INCREMENT_ID);
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => sprintf(self::RESOURCE_PATH, $order->getId()),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getStatus',
+            ],
+        ];
+
+        $this->assertEquals($order->getStatus(), $this->_webApiCall($serviceInfo, ['id' => $order->getId()]));
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d9421a9d4cd50a8e36eec50bb4c683595ee4607c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderGetTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+class OrderGetTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/order';
+
+    const SERVICE_READ_NAME = 'salesOrderRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    const ORDER_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderGet()
+    {
+        $expectedOrderData = [
+            'base_subtotal' => '100.0000',
+            'subtotal' => '100.0000',
+            'customer_is_guest' => '1',
+            'increment_id' => self::ORDER_INCREMENT_ID,
+        ];
+        $expectedPayments = ['method' => 'checkmo'];
+        $expectedBillingAddressNotEmpty = [
+            'city',
+            'postcode',
+            'lastname',
+            'street',
+            'region',
+            'telephone',
+            'country_id',
+            'firstname',
+        ];
+
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId(self::ORDER_INCREMENT_ID);
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $order->getId(),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'get',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['id' => $order->getId()]);
+
+        foreach ($expectedOrderData as $field => $value) {
+            $this->assertArrayHasKey($field, $result);
+            $this->assertEquals($value, $result[$field]);
+        }
+
+        $this->assertArrayHasKey('payments', $result);
+        foreach ($expectedPayments as $field => $value) {
+            $paymentsKey = key($result['payments']);
+            $this->assertArrayHasKey($field, $result['payments'][$paymentsKey]);
+            $this->assertEquals($value, $result['payments'][$paymentsKey][$field]);
+        }
+
+        $this->assertArrayHasKey('billing_address', $result);
+        $this->assertArrayHasKey('shipping_address', $result);
+        foreach ($expectedBillingAddressNotEmpty as $field) {
+            $this->assertArrayHasKey($field, $result['billing_address']);
+            $this->assertArrayHasKey($field, $result['shipping_address']);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderHoldTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderHoldTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a8bdc8e78a42170050fe7299415690abaf88be6a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderHoldTest.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class OrderHoldTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesOrderManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderHold()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $order = $objectManager->get('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/hold',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'hold',
+            ],
+        ];
+        $requestData = ['id' => $order->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0d9743fdbc4bca93211cc3bd2d97b6887556895
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class OrderListTest
+ * @package Magento\Sales\Service\V1
+ */
+class OrderListTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/orders';
+
+    const SERVICE_READ_NAME = 'salesOrderRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderList()
+    {
+        /** @var $searchCriteriaBuilder  \Magento\Framework\Api\SearchCriteriaBuilder */
+        $searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+
+        /** @var $filterBuilder  \Magento\Framework\Api\FilterBuilder */
+        $filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        $searchCriteriaBuilder->addFilter(
+            [
+                $filterBuilder
+                    ->setField('status')
+                    ->setValue('processing')
+                    ->create(),
+            ]
+        );
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+
+        $requestData = ['criteria' => $searchData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getList',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertArrayHasKey('items', $result);
+        $this->assertCount(1, $result['items']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderStatusHistoryAddTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderStatusHistoryAddTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9a46103a9c033ea8958f4ab373c16bea9519d89
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderStatusHistoryAddTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\OrderStatusHistoryInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class OrderCommentAddTest
+ * @package Magento\Sales\Service\V1
+ */
+class OrderStatusHistoryAddTest extends WebapiAbstract
+{
+    const SERVICE_READ_NAME = 'salesOrderManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    const ORDER_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderCommentAdd()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId(self::ORDER_INCREMENT_ID);
+
+        $commentData = [
+            OrderStatusHistoryInterface::COMMENT => 'Hello',
+            OrderStatusHistoryInterface::ENTITY_ID => null,
+            OrderStatusHistoryInterface::IS_CUSTOMER_NOTIFIED => true,
+            OrderStatusHistoryInterface::CREATED_AT => null,
+            OrderStatusHistoryInterface::PARENT_ID => $order->getId(),
+            OrderStatusHistoryInterface::ENTITY_NAME => null,
+            OrderStatusHistoryInterface::STATUS => null,
+            OrderStatusHistoryInterface::IS_VISIBLE_ON_FRONT => true,
+        ];
+
+        $requestData = ['id' => $order->getId(), 'statusHistory' => $commentData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/comment',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'addComment',
+            ],
+        ];
+
+        $this->_webApiCall($serviceInfo, $requestData);
+
+        //Verification
+        $comments = $order->load($order->getId())->getAllStatusHistory();
+
+        $commentData = reset($comments);
+        foreach ($commentData as $key => $value) {
+            $this->assertEquals($commentData[OrderStatusHistoryInterface::COMMENT], $statusHistoryComment->getComment());
+            $this->assertEquals($commentData[OrderStatusHistoryInterface::PARENT_ID], $statusHistoryComment->getParentId());
+            $this->assertEquals(
+                $commentData[OrderStatusHistoryInterface::IS_CUSTOMER_NOTIFIED], $statusHistoryComment->getIsCustomerNotified()
+            );
+            $this->assertEquals(
+                $commentData[OrderStatusHistoryInterface::IS_VISIBLE_ON_FRONT], $statusHistoryComment->getIsVisibleOnFront()
+            );
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderUnHoldTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderUnHoldTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..41d877f25b75d03ae86929389cc008c932243e24
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderUnHoldTest.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class OrderUnHoldTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesOrderManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testOrderUnHold()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $objectManager->get('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        if ($order->canHold()) {
+            $order->hold()->save();
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/order/' . $order->getId() . '/unhold',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'unHold',
+            ],
+        ];
+        $requestData = ['id' => $order->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddCommentTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddCommentTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..dbdd8768fcedf49aa9c13e2c5eb55468c3c3e597
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddCommentTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\ShipmentCommentInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentAddCommentTest
+ */
+class ShipmentAddCommentTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesShipmentCommentRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Shipment increment id
+     */
+    const SHIPMENT_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test shipment add comment service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentAddComment()
+    {
+        /** @var \Magento\Sales\Model\Resource\Order\Shipment\Collection $shipmentCollection */
+        $shipmentCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+
+        $commentData = [
+            ShipmentCommentInterface::COMMENT => 'Hello world!',
+            ShipmentCommentInterface::ENTITY_ID => null,
+            ShipmentCommentInterface::CREATED_AT => null,
+            ShipmentCommentInterface::PARENT_ID => $shipment->getId(),
+            ShipmentCommentInterface::IS_VISIBLE_ON_FRONT => true,
+            ShipmentCommentInterface::IS_CUSTOMER_NOTIFIED => true,
+        ];
+
+        $requestData = ['entity' => $commentData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/shipment/comment',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddTrackTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddTrackTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..af1e624793ab4adf4db0d05c5d0ce53efadbfb7a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentAddTrackTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\ShipmentTrackInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentAddTrackTest
+ */
+class ShipmentAddTrackTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesShipmentTrackRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Shipment increment id
+     */
+    const SHIPMENT_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test shipment add track service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentAddTrack()
+    {
+        /** @var \Magento\Sales\Model\Order\Shipment $shipment */
+        $shipmentCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+
+        $trackData = [
+            ShipmentTrackInterface::ENTITY_ID => null,
+            ShipmentTrackInterface::ORDER_ID => $shipment->getOrderId(),
+            ShipmentTrackInterface::CREATED_AT => null,
+            ShipmentTrackInterface::PARENT_ID => $shipment->getId(),
+            ShipmentTrackInterface::WEIGHT => 20,
+            ShipmentTrackInterface::QTY => 5,
+            ShipmentTrackInterface::TRACK_NUMBER => 2,
+            ShipmentTrackInterface::DESCRIPTION => 'Shipment description',
+            ShipmentTrackInterface::TITLE => 'Shipment title',
+            ShipmentTrackInterface::CARRIER_CODE => \Magento\Sales\Model\Order\Shipment\Track::CUSTOM_CARRIER_CODE,
+            ShipmentTrackInterface::CREATED_AT => null,
+            ShipmentTrackInterface::UPDATED_AT => null,
+        ];
+
+        $requestData = ['entity' => $trackData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/shipment/track',
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCommentsListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCommentsListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea79127aee85f7b1a81369f6671c90e2afa7020c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCommentsListTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class ShipmentCommentsListTest
+ */
+class ShipmentCommentsListTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'salesShipmentManagementV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentCommentsList()
+    {
+        $comment = 'Test comment';
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+        /** @var \Magento\Sales\Model\Resource\Order\Shipment\Collection $shipmentCollection */
+        $shipmentCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+        $shipmentComment = $objectManager->get('Magento\Sales\Model\Order\Shipment\Comment');
+        $shipmentComment->setComment($comment);
+        $shipmentComment->setParentId($shipment->getId());
+        $shipmentComment->save();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/shipment/' . $shipment->getId() . '/comments',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'getCommentsList',
+            ],
+        ];
+        $requestData = ['id' => $shipment->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        foreach ($result['items'] as $item) {
+            /** @var \Magento\Sales\Model\Order\Shipment\Comment $shipmentHistoryStatus */
+            $shipmentHistoryStatus = $objectManager->get('Magento\Sales\Model\Order\Shipment\Comment')
+                ->load($item['entity_id']);
+            $this->assertEquals($shipmentHistoryStatus->getComment(), $item['comment']);
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b73cd43ee8299cdf7e612e755928cf4043315af9
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentCreateTest
+ */
+class ShipmentCreateTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/shipment';
+
+    const SERVICE_READ_NAME = 'salesShipmentRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/order.php
+     */
+    public function testInvoke()
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId('100000001');
+        $orderItem = current($order->getAllItems());
+        $items = [
+            [
+                'order_item_id' => $orderItem->getId(),
+                'qty' => $orderItem->getQtyOrdered(),
+                'additional_data' => null,
+                'description' => null,
+                'entity_id' => null,
+                'name' => null,
+                'parent_id' => null,
+                'price' => null,
+                'product_id' => null,
+                'row_total' => null,
+                'sku' => null,
+                'weight' => null,
+            ],
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'save',
+            ],
+        ];
+        $data = [
+            'order_id' => $order->getId(),
+            'entity_id' => null,
+            'store_id' => null,
+            'total_weight' => null,
+            'total_qty' => null,
+            'email_sent' => null,
+            'customer_id' => null,
+            'shipping_address_id' => null,
+            'billing_address_id' => null,
+            'shipment_status' => null,
+            'increment_id' => null,
+            'created_at' => null,
+            'updated_at' => null,
+//            'packages' => null,
+            'shipping_label' => null,
+            'tracks' => [],
+            'items' => $items,
+            'comments' => [],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['entity' => $data]);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentEmailTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentEmailTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3329e8addf061b734d575a3a99883897ae1e8d4c
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentEmailTest.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class ShipmentEmailTest
+ */
+class ShipmentEmailTest extends WebapiAbstract
+{
+    const SERVICE_VERSION = 'V1';
+
+    const SERVICE_NAME = 'salesShipmentManagementV1';
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentEmail()
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $shipmentCollection = $objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/shipment/' . $shipment->getId() . '/email',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'notify',
+            ],
+        ];
+        $requestData = ['id' => $shipment->getId()];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentGetTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentGetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bc2a21698d8dedd25c4b0f6100d21bd9d446bef
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentGetTest.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentGetTest
+ */
+class ShipmentGetTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/shipment';
+    const SERVICE_READ_NAME = 'salesShipmentRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentGet()
+    {
+        /** @var \Magento\Sales\Model\Order\Shipment $shipment */
+        $shipmentCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+        $shipment->load($shipment->getId());
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $shipment->getId(),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'get',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['id' => $shipment->getId()]);
+        $data = $result;
+        $this->assertArrayHasKey('items', $result);
+        $this->assertArrayHasKey('tracks', $result);
+        unset($data['items']);
+        unset($data['packages']);
+        unset($data['tracks']);
+        foreach ($data as $key => $value) {
+            if (!empty($value)) {
+                $this->assertEquals($shipment->getData($key), $value, $key);
+            }
+        }
+        $shipmentItem = $this->objectManager->get('Magento\Sales\Model\Order\Shipment\Item');
+        foreach ($result['items'] as $item) {
+            $shipmentItem->load($item['entity_id']);
+            foreach ($item as $key => $value) {
+                $this->assertEquals($shipmentItem->getData($key), $value, $key);
+            }
+        }
+        $shipmentTrack = $this->objectManager->get('Magento\Sales\Model\Order\Shipment\Track');
+        foreach ($result['tracks'] as $item) {
+            $shipmentTrack->load($item['entity_id']);
+            foreach ($item as $key => $value) {
+                $this->assertEquals($shipmentTrack->getData($key), $value, $key);
+            }
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentLabelGetTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentLabelGetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f03bad65a110117b8bdbf1f2e199047862f01ffc
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentLabelGetTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentLabelGetTest
+ */
+class ShipmentLabelGetTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/shipment';
+    const SERVICE_READ_NAME = 'salesShipmentManagementV1';
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentGet()
+    {
+        /** @var \Magento\Sales\Model\Order\Shipment $shipment */
+        $shipmentCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+        $shipment->setShippingLabel('test_shipping_label');
+        $shipment->save();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $shipment->getId() . '/label',
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getLabel',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['id' => $shipment->getId()]);
+        $this->assertEquals($result, 'test_shipping_label');
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b68d6900eab7879332577843259123c8465b4f2a
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentListTest
+ */
+class ShipmentListTest extends WebapiAbstract
+{
+    const RESOURCE_PATH = '/V1/shipments';
+
+    const SERVICE_READ_NAME = 'salesShipmentRepositoryV1';
+
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentList()
+    {
+        /** @var $searchCriteriaBuilder  \Magento\Framework\Api\SearchCriteriaBuilder */
+        $searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+
+        /** @var $filterBuilder  \Magento\Framework\Api\FilterBuilder */
+        $filterBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        $searchCriteriaBuilder->addFilter([$filterBuilder->setField('shipment_status')->setValue(1)->create()]);
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+
+        $requestData = ['criteria' => $searchData];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getList',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        // TODO Test fails, due to the inability of the framework API to handle data collection
+        $this->assertArrayHasKey('items', $result);
+        $this->assertCount(1, $result['items']);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentRemoveTrackTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentRemoveTrackTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4dc7637b37de6588e998f919d7d1e8c00f6ba0fe
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentRemoveTrackTest.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Api\Data\ShipmentTrackInterface;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class ShipmentRemoveTrackTest
+ */
+class ShipmentRemoveTrackTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesShipmentTrackRepositoryV1';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * Shipment increment id
+     */
+    const SHIPMENT_INCREMENT_ID = '100000001';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Test shipment remove track service
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/shipment.php
+     */
+    public function testShipmentRemoveTrack()
+    {
+        /** @var \Magento\Sales\Model\Order\Shipment $shipment */
+        $shipmentCollection = $this->objectManager->get('Magento\Sales\Model\Resource\Order\Shipment\Collection');
+        $shipment = $shipmentCollection->getFirstItem();
+
+        /** @var \Magento\Sales\Model\Order\Shipment\Track $track */
+        $track = $this->objectManager->create('Magento\Sales\Model\Order\Shipment\TrackFactory')->create();
+        $track->addData(
+            [
+                ShipmentTrackInterface::ENTITY_ID => null,
+                ShipmentTrackInterface::ORDER_ID => 12,
+                ShipmentTrackInterface::CREATED_AT => null,
+                ShipmentTrackInterface::PARENT_ID => $shipment->getId(),
+                ShipmentTrackInterface::WEIGHT => 20,
+                ShipmentTrackInterface::QTY => 5,
+                ShipmentTrackInterface::TRACK_NUMBER => 2,
+                ShipmentTrackInterface::DESCRIPTION => 'Shipment description',
+                ShipmentTrackInterface::TITLE => 'Shipment title',
+                ShipmentTrackInterface::CARRIER_CODE => \Magento\Sales\Model\Order\Shipment\Track::CUSTOM_CARRIER_CODE,
+                ShipmentTrackInterface::CREATED_AT => null,
+                ShipmentTrackInterface::UPDATED_AT => null,
+            ]
+        );
+        $track->save();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/shipment/track/' . $track->getId(),
+                'httpMethod' => Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'deleteById',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, ['id' => $track->getId()]);
+        $this->assertNotEmpty($result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2138fd6a6afa7ec3085fcdd5d89f80004551d2fa
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php
@@ -0,0 +1,190 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Sales\Service\V1;
+
+use Magento\Sales\Model\Order;
+use Magento\Sales\Model\Order\Payment;
+use Magento\Sales\Model\Order\Payment\Transaction;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config;
+
+/**
+ * Class TransactionReadTest
+ */
+class TransactionTest extends WebapiAbstract
+{
+    /**
+     * Service read name
+     */
+    const SERVICE_READ_NAME = 'salesTransactionRepositoryV1';
+
+    /**
+     * Resource path for REST
+     */
+    const RESOURCE_PATH = '/V1/transactions';
+
+    /**
+     * Service version
+     */
+    const SERVICE_VERSION = 'V1';
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface
+     */
+    protected $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Tests list of order transactions
+     *
+     * @magentoApiDataFixture Magento/Sales/_files/transactions_detailed.php
+     */
+    public function testTransactionGet()
+    {
+        /** @var Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId('100000006');
+
+        /** @var Payment $payment */
+        $payment = $order->getPayment();
+        /** @var Transaction $transaction */
+        $transaction = $payment->getTransaction('trx_auth');
+
+        $childTransactions = $transaction->getChildTransactions();
+        $childTransaction = reset($childTransactions);
+
+        $expectedData = $this->getPreparedTransactionData($transaction);
+        $childTransactionData = $this->getPreparedTransactionData($childTransaction);
+        $expectedData['child_transactions'][] = $childTransactionData;
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $transaction->getId(),
+                'httpMethod' => Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'get',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['id' => $transaction->getId()]);
+        ksort($expectedData);
+        ksort($result);
+        $this->assertEquals($expectedData, $result);
+    }
+
+    /**
+     * Tests list of order transactions
+     * @dataProvider filtersDataProvider
+     */
+    public function testTransactionList($filters)
+    {
+        /** @var Order $order */
+        $order = $this->objectManager->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId('100000006');
+
+        /** @var Payment $payment */
+        $payment = $order->getPayment();
+        /** @var Transaction $transaction */
+        $transaction = $payment->getTransaction('trx_auth');
+
+        $childTransactions = $transaction->getChildTransactions();
+
+        $childTransaction = reset($childTransactions);
+
+        /** @var $searchCriteriaBuilder  \Magento\Framework\Api\SearchCriteriaBuilder */
+        $searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+
+        $searchCriteriaBuilder->addFilter($filters);
+        $searchData = $searchCriteriaBuilder->create()->__toArray();
+
+        $requestData = ['criteria' => $searchData];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
+                'httpMethod' => Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_READ_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_READ_NAME . 'getList',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertArrayHasKey('items', $result);
+
+        $transactionData = $this->getPreparedTransactionData($transaction);
+        $childTransactionData = $this->getPreparedTransactionData($childTransaction);
+        $transactionData['child_transactions'][] = $childTransactionData;
+        $expectedData = [$transactionData, $childTransactionData];
+
+        $this->assertEquals($expectedData, $result['items']);
+    }
+
+    /**
+     * @param Transaction $transaction
+     * @return array
+     */
+    private function getPreparedTransactionData(Transaction $transaction)
+    {
+        $additionalInfo = [];
+        foreach ($transaction->getAdditionalInformation() as $value) {
+            $additionalInfo[] = $value;
+        }
+
+        $expectedData = ['transaction_id' => (int)$transaction->getId()];
+
+        if (!is_null($transaction->getParentId())) {
+            $expectedData['parent_id'] = (int)$transaction->getParentId();
+        }
+
+        $expectedData = array_merge(
+            $expectedData,
+            [
+                'order_id' => (int)$transaction->getOrderId(),
+                'payment_id' => (int)$transaction->getPaymentId(),
+                'txn_id' => $transaction->getTxnId(),
+                'parent_txn_id' => ($transaction->getParentTxnId() ? (string)$transaction->getParentTxnId() : ''),
+                'txn_type' => $transaction->getTxnType(),
+                'is_closed' => (int)$transaction->getIsClosed(),
+                'additional_information' => ['data'],
+                'created_at' => $transaction->getCreatedAt(),
+                'child_transactions' => [],
+            ]
+        );
+
+        return $expectedData;
+    }
+
+    /**
+     * @return array
+     */
+    public function filtersDataProvider()
+    {
+        /** @var $filterBuilder  \Magento\Framework\Api\FilterBuilder */
+        $filterBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        return [
+            [
+                [
+                    $filterBuilder->setField('created_at')->setValue('2020-12-12 00:00:00')
+                        ->setConditionType('lteq')->create(),
+                ],
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a462cbc3fb321bcc0447c9e4dda6aef70c33633
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxClassRepositoryTest.php
@@ -0,0 +1,309 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Tax\Api;
+
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Tax\Api\Data\TaxClassDataBuilder;
+use Magento\Tax\Model\ClassModelRegistry;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Tests for tax class service.
+ */
+class TaxClassRepositoryTest extends WebapiAbstract
+{
+    const SERVICE_NAME = 'taxTaxClassRepositoryV1';
+    const SERVICE_VERSION = 'V1';
+    const RESOURCE_PATH = '/V1/taxClass';
+
+    /** @var SearchCriteriaBuilder */
+    private $searchCriteriaBuilder;
+
+    /** @var FilterBuilder */
+    private $filterBuilder;
+
+    /** @var TaxClassDataBuilder */
+    private $taxClassBuilder;
+
+    /** @var TaxClassRepositoryInterface */
+    private $taxClassRepository;
+
+    /** @var ClassModelRegistry */
+    private $taxClassRegistry;
+
+    const SAMPLE_TAX_CLASS_NAME = 'Wholesale Customer';
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->filterBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+        $this->taxClassBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Tax\Api\Data\TaxClassDataBuilder'
+        );
+        $this->taxClassRegistry = Bootstrap::getObjectManager()->create(
+            'Magento\Tax\Model\ClassModelRegistry'
+        );
+        $this->taxClassRepository = Bootstrap::getObjectManager()->create(
+            'Magento\Tax\Model\TaxClass\Repository',
+            ['classModelRegistry' => $this->taxClassRegistry]
+        );
+    }
+
+    /**
+     * Test create Data\TaxClassInterface
+     */
+    public function testCreateTaxClass()
+    {
+        $taxClassName = self::SAMPLE_TAX_CLASS_NAME . uniqid();
+        /** @var  \Magento\Tax\Api\Data\TaxClassInterface $taxClassDataObject */
+        $taxClassDataObject = $this->taxClassBuilder->setClassName($taxClassName)
+            ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER)
+            ->create();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        $requestData = ['taxClass' => [
+                'class_id' => $taxClassDataObject->getClassId(),
+                'class_name' => $taxClassDataObject->getClassName(),
+                'class_type' => $taxClassDataObject->getClassType(),
+            ],
+        ];
+        $taxClassId = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertNotNull($taxClassId);
+
+        //Verify by getting the Data\TaxClassInterface
+        $taxClassData = $this->taxClassRepository->get($taxClassId);
+        $this->assertEquals($taxClassData->getClassName(), $taxClassName);
+        $this->assertEquals($taxClassData->getClassType(), TaxClassManagementInterface::TYPE_CUSTOMER);
+    }
+
+    /**
+     * Test create Data\TaxClassInterface
+     */
+    public function testUpdateTaxClass()
+    {
+        //Create Tax Class
+        $taxClassDataObject = $this->taxClassBuilder->setClassName(self::SAMPLE_TAX_CLASS_NAME . uniqid())
+            ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER)
+            ->create();
+        $taxClassId = $this->taxClassRepository->save($taxClassDataObject);
+        $this->assertNotNull($taxClassId);
+
+        //Update Tax Class
+        $updatedTaxClassName = self::SAMPLE_TAX_CLASS_NAME . uniqid();
+        $updatedTaxClassDataObject = $this->taxClassBuilder
+            ->populate($taxClassDataObject)
+            ->setClassName($updatedTaxClassName)
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $taxClassId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+
+        $taxClass = [
+                'class_id' => $updatedTaxClassDataObject->getClassId(),
+                'class_name' => $updatedTaxClassDataObject->getClassName(),
+                'class_type' => $updatedTaxClassDataObject->getClassType(),
+            ];
+
+        $requestData = ['taxClass' => $taxClass, 'ClassId' => $taxClassId];
+
+        $this->assertEquals($taxClassId, $this->_webApiCall($serviceInfo, $requestData));
+
+        //Verify by getting the Data\TaxClassInterface
+        $this->taxClassRegistry->remove($taxClassId);
+        $taxClassData = $this->taxClassRepository->get($taxClassId);
+        $this->assertEquals($taxClassData->getClassName(), $updatedTaxClassName);
+    }
+
+    public function testGetTaxClass()
+    {
+        //Create Tax Class
+        $taxClassName = self::SAMPLE_TAX_CLASS_NAME . uniqid();
+        $taxClassDataObject = $this->taxClassBuilder->setClassName($taxClassName)
+            ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER)
+            ->create();
+        $taxClassId = $this->taxClassRepository->save($taxClassDataObject);
+        $this->assertNotNull($taxClassId);
+
+        //Verify by getting the Data\TaxClassInterface
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $taxClassId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        $requestData = ['taxClassId' => $taxClassId];
+        $taxClassData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($taxClassData[Data\TaxClassInterface::KEY_NAME], $taxClassName);
+        $this->assertEquals(
+            $taxClassData[Data\TaxClassInterface::KEY_TYPE],
+            TaxClassManagementInterface::TYPE_CUSTOMER
+        );
+    }
+
+    /**
+     * Test delete Tax class
+     */
+    public function testDeleteTaxClass()
+    {
+        $taxClassDataObject = $this->taxClassBuilder->setClassName(self::SAMPLE_TAX_CLASS_NAME . uniqid())
+            ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER)
+            ->create();
+        $taxClassId = $this->taxClassRepository->save($taxClassDataObject);
+        $this->assertNotNull($taxClassId);
+
+        //Verify by getting the Data\TaxClassInterface
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/' . $taxClassId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        $requestData = ['taxClassId' => $taxClassId];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+
+        try {
+            $this->taxClassRegistry->remove($taxClassId);
+            $this->taxClassRepository->get($taxClassId);
+            $this->fail("Tax class was not expected to be returned after being deleted.");
+        } catch (NoSuchEntityException $e) {
+            $this->assertEquals('No such entity with class_id = ' . $taxClassId, $e->getMessage());
+        }
+    }
+
+    /**
+     * Test with a single filter
+     */
+    public function testSearchTaxClass()
+    {
+        $taxClassName = 'Retail Customer';
+        $taxClassNameField = Data\TaxClassInterface::KEY_NAME;
+        $filter = $this->filterBuilder->setField($taxClassNameField)
+            ->setValue($taxClassName)
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($taxClassName, $searchResults['items'][0][$taxClassNameField]);
+    }
+
+    /**
+     * Test using multiple filters
+     */
+    public function testSearchTaxClassMultipleFilterGroups()
+    {
+        $productTaxClass = [
+            Data\TaxClassInterface::KEY_NAME => 'Taxable Goods',
+            Data\TaxClassInterface::KEY_TYPE => 'PRODUCT',
+        ];
+        $customerTaxClass = [Data\TaxClassInterface::KEY_NAME => 'Retail Customer',
+            Data\TaxClassInterface::KEY_TYPE => 'CUSTOMER', ];
+
+        $filter1 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_NAME)
+            ->setValue($productTaxClass[Data\TaxClassInterface::KEY_NAME])
+            ->create();
+        $filter2 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_NAME)
+            ->setValue($customerTaxClass[Data\TaxClassInterface::KEY_NAME])
+            ->create();
+        $filter3 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_TYPE)
+            ->setValue($productTaxClass[Data\TaxClassInterface::KEY_TYPE])
+            ->create();
+        $filter4 = $this->filterBuilder->setField(Data\TaxClassInterface::KEY_TYPE)
+            ->setValue($customerTaxClass[Data\TaxClassInterface::KEY_TYPE])
+            ->create();
+
+        /**
+         * (class_name == 'Retail Customer' || class_name == 'Taxable Goods)
+         * && ( class_type == 'CUSTOMER' || class_type == 'PRODUCT')
+         */
+        $this->searchCriteriaBuilder->addFilter([$filter1, $filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3, $filter4]);
+        $searchCriteria = $this->searchCriteriaBuilder->setCurrentPage(1)->setPageSize(10)->create();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(2, $searchResults['total_count']);
+        $this->assertEquals($productTaxClass[Data\TaxClassInterface::KEY_NAME],
+            $searchResults['items'][0][Data\TaxClassInterface::KEY_NAME]);
+        $this->assertEquals($customerTaxClass[Data\TaxClassInterface::KEY_NAME],
+            $searchResults['items'][1][Data\TaxClassInterface::KEY_NAME]);
+
+        /** class_name == 'Retail Customer' && ( class_type == 'CUSTOMER' || class_type == 'PRODUCT') */
+        $this->searchCriteriaBuilder->addFilter([$filter2]);
+        $this->searchCriteriaBuilder->addFilter([$filter3, $filter4]);
+        $searchCriteria = $this->searchCriteriaBuilder->create();
+        $searchData = $searchCriteria->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($customerTaxClass[Data\TaxClassInterface::KEY_NAME],
+            $searchResults['items'][0][Data\TaxClassInterface::KEY_NAME]);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0122bdfa3d7d1e751f1aa709e35f13f3cdca0639
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRateRepositoryTest.php
@@ -0,0 +1,660 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Tax\Api;
+
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\SearchCriteria;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\Api\SortOrderBuilder;
+use Magento\Tax\Api\Data\TaxRateInterface as TaxRate;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+
+class TaxRateRepositoryTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "taxTaxRateRepositoryV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/taxRate";
+
+    /** @var \Magento\Tax\Model\Calculation\Rate[] */
+    private $fixtureTaxRates;
+
+    /** @var \Magento\Tax\Model\ClassModel[] */
+    private $fixtureTaxClasses;
+
+    /** @var \Magento\Tax\Model\Calculation\Rule[] */
+    private $fixtureTaxRules;
+
+    /**
+     * @var \Magento\Tax\Api\TaxRateRepositoryInterface
+     */
+    private $taxRateService;
+
+    /** @var FilterBuilder */
+    private $filterBuilder;
+
+    /** @var SearchCriteriaBuilder */
+    private $searchCriteriaBuilder;
+
+    /** @var  SortOrderBuilder */
+    private $sortOrderBuilder;
+
+    /**
+     * Other rates created during tests, to be deleted in tearDown()
+     *
+     * @var \Magento\Tax\Model\Calculation\Rate[]
+     */
+    private $otherRates = [];
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+        $this->taxRateService = $objectManager->get('Magento\Tax\Api\TaxRateRepositoryInterface');
+        $this->searchCriteriaBuilder = $objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->filterBuilder = $objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+        $this->sortOrderBuilder = $objectManager->create(
+            'Magento\Framework\Api\SortOrderBuilder'
+        );
+        /** Initialize tax classes, tax rates and tax rules defined in fixture Magento/Tax/_files/tax_classes.php */
+        $this->getFixtureTaxRates();
+        $this->getFixtureTaxClasses();
+        $this->getFixtureTaxRules();
+    }
+
+    public function tearDown()
+    {
+        $taxRules = $this->getFixtureTaxRules();
+        if (count($taxRules)) {
+            $taxRates = $this->getFixtureTaxRates();
+            $taxClasses = $this->getFixtureTaxClasses();
+            foreach ($taxRules as $taxRule) {
+                $taxRule->delete();
+            }
+            foreach ($taxRates as $taxRate) {
+                $taxRate->delete();
+            }
+            foreach ($taxClasses as $taxClass) {
+                $taxClass->delete();
+            }
+        }
+        if (count($this->otherRates)) {
+            foreach ($this->otherRates as $taxRate) {
+                $taxRate->delete();
+            }
+        }
+    }
+
+    public function testCreateTaxRateExistingCode()
+    {
+        $data = [
+            'tax_rate' => [
+                'tax_country_id' => 'US',
+                'tax_region_id' => 12,
+                'tax_postcode' => '*',
+                'code' => 'US-CA-*-Rate 1',
+                'rate' => '8.2501',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $data);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'Code already exists.';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    public function testCreateTaxRate()
+    {
+        $data = [
+            'tax_rate' => [
+                'tax_country_id' => 'US',
+                'tax_region_id' => 12,
+                'tax_postcode' => '*',
+                'code' => 'Test Tax Rate ' . microtime(),
+                'rate' => '8.2501',
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $data);
+        $this->assertArrayHasKey('id', $result);
+        $taxRateId = $result['id'];
+        /** Ensure that tax rate was actually created in DB */
+        /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+        $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+        $this->assertEquals($taxRateId, $taxRate->load($taxRateId)->getId(), 'Tax rate was not created in  DB.');
+        $taxRate->delete();
+    }
+
+    public function testCreateTaxRateWithZipRange()
+    {
+        $data = [
+            'tax_rate' => [
+                'tax_country_id' => 'US',
+                'tax_region_id' => 12,
+                'code' => 'Test Tax Rate ' . microtime(),
+                'rate' => '8.2501',
+                'zip_is_range' => 1,
+                'zip_from' => 17,
+                'zip_to' => 25,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, $data);
+        $this->assertArrayHasKey('id', $result);
+        $taxRateId = $result['id'];
+        /** Ensure that tax rate was actually created in DB */
+        /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+        $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+        $this->assertEquals($taxRateId, $taxRate->load($taxRateId)->getId(), 'Tax rate was not created in  DB.');
+        $this->assertEquals('17-25', $taxRate->getTaxPostcode(), 'Zip range is not saved in DB.');
+        $taxRate->delete();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testUpdateTaxRate()
+    {
+        $fixtureRate = $this->getFixtureTaxRates()[0];
+
+        $data = [
+            'tax_rate' => [
+                'id' => $fixtureRate->getId(),
+                'tax_region_id' => 43,
+                'tax_country_id' => 'US',
+                'tax_postcode' => '07400',
+                'code' => 'Test Tax Rate ' . microtime(),
+                'rate' => 3.456,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, $data);
+        $expectedRateData = $data['tax_rate'];
+        /** Ensure that tax rate was actually updated in DB */
+        /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+        $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+        $taxRateModel = $taxRate->load($fixtureRate->getId());
+        $this->assertEquals($expectedRateData['id'], $taxRateModel->getId(), 'Tax rate was not updated in  DB.');
+        $this->assertEquals(
+            $expectedRateData['tax_region_id'],
+            $taxRateModel->getTaxRegionId(),
+            'Tax rate was not updated in  DB.'
+        );
+        $this->assertEquals(
+            $expectedRateData['tax_country_id'],
+            $taxRateModel->getTaxCountryId(),
+            'Tax rate was not updated in  DB.'
+        );
+        $this->assertEquals(
+            $expectedRateData['tax_postcode'],
+            $taxRateModel->getTaxPostcode(),
+            'Tax rate was not updated in  DB.'
+        );
+        $this->assertEquals($expectedRateData['code'], $taxRateModel->getCode(), 'Tax rate was not updated in  DB.');
+        $this->assertEquals(
+            $expectedRateData['rate'],
+            $taxRateModel->getRate(),
+            'Tax rate was not updated in  DB.'
+        );
+    }
+
+    public function testUpdateTaxRateNotExisting()
+    {
+        $data = [
+            'tax_rate' => [
+                'id' => 555,
+                'tax_region_id' => 43,
+                'tax_country_id' => 'US',
+                'tax_postcode' => '07400',
+                'code' => 'Test Tax Rate ' . microtime(),
+                'rate' => 3.456,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $data);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    public function testGetTaxRate()
+    {
+        $taxRateId = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
+        $expectedRateData = [
+            'id' => 2,
+            'tax_country_id' => 'US',
+            'tax_region_id' => 43,
+            'tax_postcode' => '*',
+            'code' => 'US-NY-*-Rate 1',
+            'rate' => 8.375,
+            'titles' => [],
+            'region_name' => 'NY',
+        ];
+        $this->assertEquals($expectedRateData, $result);
+    }
+
+    public function testGetTaxRateNotExist()
+    {
+        $taxRateId = 37865;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testDeleteTaxRate()
+    {
+        /** Tax rules must be deleted since tax rate cannot be deleted if there are any tax rules associated with it */
+        $taxRules = $this->getFixtureTaxRules();
+        foreach ($taxRules as $taxRule) {
+            $taxRule->delete();
+        }
+
+        $fixtureRate = $this->getFixtureTaxRates()[0];
+        $taxRateId = $fixtureRate->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
+        $this->assertTrue($result);
+        /** Ensure that tax rate was actually removed from DB */
+        /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+        $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+        $this->assertNull($taxRate->load($taxRateId)->getId(), 'Tax rate was not deleted from DB.');
+    }
+
+    /**
+     * Insure that tax rate cannot be deleted if it is used for a tax rule.
+     *
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testCannotDeleteTaxRate()
+    {
+        $fixtureRate = $this->getFixtureTaxRates()[0];
+        $taxRateId = $fixtureRate->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRateId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, ['rateId' => $taxRateId]);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'The tax rate cannot be removed. It exists in a tax rule.';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    public function testSearchTaxRates()
+    {
+        $rates = $this->setupTaxRatesForSearch();
+
+        // Find rates whose code is 'codeUs12'
+        $filter = $this->filterBuilder->setField(TaxRate::KEY_CODE)
+            ->setValue('codeUs12')
+            ->create();
+
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+
+        /** @var \Magento\Framework\Api\SearchResults $searchResults */
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals(1, $searchResults['total_count']);
+
+        $expectedRuleData = [
+            [
+                'id' => (int)$rates['codeUs12']->getId(),
+                'tax_country_id' => $rates['codeUs12']->getTaxCountryId(),
+                'tax_region_id' => (int)$rates['codeUs12']->getTaxRegionId(),
+                'region_name' => 'CA',
+                'tax_postcode' => $rates['codeUs12']->getTaxPostcode(),
+                'code' =>  $rates['codeUs12']->getCode(),
+                'rate' => ((float) $rates['codeUs12']->getRate()),
+                'titles' => [],
+            ],
+        ];
+        $this->assertEquals($expectedRuleData, $searchResults['items']);
+    }
+
+    public function testSearchTaxRatesCz()
+    {
+        // TODO: This test fails in SOAP, a generic bug searching in SOAP
+        $this->_markTestAsRestOnly();
+        $rates = $this->setupTaxRatesForSearch();
+
+        // Find rates which country id 'CZ'
+        $filter = $this->filterBuilder->setField(TaxRate::KEY_COUNTRY_ID)
+            ->setValue('CZ')
+            ->create();
+        $sortOrder = $this->sortOrderBuilder
+            ->setField(TaxRate::KEY_POSTCODE)
+            ->setDirection(SearchCriteria::SORT_DESC)
+            ->create();
+        // Order them by descending postcode (not the default order)
+        $this->searchCriteriaBuilder->addFilter([$filter])
+            ->addSortOrder($sortOrder);
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+
+        /** @var \Magento\Framework\Api\SearchResults $searchResults */
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals(2, $searchResults['total_count']);
+
+        $expectedRuleData = [
+            [
+                'id' => (int)$rates['codeCz2']->getId(),
+                'tax_country_id' => $rates['codeCz2']->getTaxCountryId(),
+                'tax_postcode' => $rates['codeCz2']->getTaxPostcode(),
+                'code' =>  $rates['codeCz2']->getCode(),
+                'rate' =>  ((float) $rates['codeCz2']->getRate()),
+                'tax_region_id' => 0,
+                'titles' => [],
+            ],
+            [
+                'id' => (int)$rates['codeCz1']->getId(),
+                'tax_country_id' => $rates['codeCz1']->getTaxCountryId(),
+                'tax_postcode' => $rates['codeCz1']->getTaxPostcode(),
+                'code' => $rates['codeCz1']->getCode(),
+                'rate' => ((float) $rates['codeCz1']->getRate()),
+                'tax_region_id' => 0,
+                'titles' => [],
+            ],
+        ];
+        $this->assertEquals($expectedRuleData, $searchResults['items']);
+    }
+
+    /**
+     * Get tax rates created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\Calculation\Rate[]
+     */
+    private function getFixtureTaxRates()
+    {
+        if (is_null($this->fixtureTaxRates)) {
+            $this->fixtureTaxRates = [];
+            if ($this->getFixtureTaxRules()) {
+                $taxRateIds = (array)$this->getFixtureTaxRules()[0]->getRates();
+                foreach ($taxRateIds as $taxRateId) {
+                    /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+                    $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+                    $this->fixtureTaxRates[] = $taxRate->load($taxRateId);
+                }
+            }
+        }
+        return $this->fixtureTaxRates;
+    }
+
+    /**
+     * Get tax classes created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\ClassModel[]
+     */
+    private function getFixtureTaxClasses()
+    {
+        if (is_null($this->fixtureTaxClasses)) {
+            $this->fixtureTaxClasses = [];
+            if ($this->getFixtureTaxRules()) {
+                $taxClassIds = array_merge(
+                    (array)$this->getFixtureTaxRules()[0]->getCustomerTaxClasses(),
+                    (array)$this->getFixtureTaxRules()[0]->getProductTaxClasses()
+                );
+                foreach ($taxClassIds as $taxClassId) {
+                    /** @var \Magento\Tax\Model\ClassModel $taxClass */
+                    $taxClass = Bootstrap::getObjectManager()->create('Magento\Tax\Model\ClassModel');
+                    $this->fixtureTaxClasses[] = $taxClass->load($taxClassId);
+                }
+            }
+        }
+        return $this->fixtureTaxClasses;
+    }
+
+    /**
+     * Get tax rule created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\Calculation\Rule[]
+     */
+    private function getFixtureTaxRules()
+    {
+        if (is_null($this->fixtureTaxRules)) {
+            $this->fixtureTaxRules = [];
+            $taxRuleCodes = ['Test Rule Duplicate', 'Test Rule'];
+            foreach ($taxRuleCodes as $taxRuleCode) {
+                /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+                $taxRule = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rule');
+                $taxRule->load($taxRuleCode, 'code');
+                if ($taxRule->getId()) {
+                    $this->fixtureTaxRules[] = $taxRule;
+                }
+            }
+        }
+        return $this->fixtureTaxRules;
+    }
+
+    /**
+     * Creates rates for search tests.
+     *
+     * @return \Magento\Tax\Model\Calculation\Rate[]
+     */
+    private function setupTaxRatesForSearch()
+    {
+        $objectManager = Bootstrap::getObjectManager();
+
+        $taxRateUs12 = [
+            'tax_country_id' => 'US',
+            'tax_region_id' => 12,
+            'tax_postcode' => '*',
+            'code' => 'codeUs12',
+            'rate' => 22,
+            'region_name' => 'CA',
+        ];
+        $rates['codeUs12'] = $objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($taxRateUs12)
+            ->save();
+
+        $taxRateUs14 = [
+            'tax_country_id' => 'US',
+            'tax_region_id' => 14,
+            'tax_postcode' => '*',
+            'code' => 'codeUs14',
+            'rate' => 22,
+        ];
+        $rates['codeUs14'] = $objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($taxRateUs14)
+            ->save();
+        $taxRateBr13 = [
+            'tax_country_id' => 'BR',
+            'tax_region_id' => 13,
+            'tax_postcode' => '*',
+            'code' => 'codeBr13',
+            'rate' => 7.5,
+        ];
+        $rates['codeBr13'] = $objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($taxRateBr13)
+            ->save();
+
+        $taxRateCz1 = [
+            'tax_country_id' => 'CZ',
+            'tax_postcode' => '110 00',
+            'code' => 'codeCz1',
+            'rate' => 1.1,
+        ];
+        $rates['codeCz1'] = $objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($taxRateCz1)
+            ->save();
+        $taxRateCz2 = [
+            'tax_country_id' => 'CZ',
+            'tax_postcode' => '250 00',
+            'code' => 'codeCz2',
+            'rate' => 2.2,
+        ];
+        $rates['codeCz2'] = $objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($taxRateCz2)
+            ->save();
+
+        // Set class variable so rates will be deleted on tearDown()
+        $this->otherRates = $rates;
+        return $rates;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRuleRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRuleRepositoryInterfaceTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..277b0611d7acbb12ad62fe8c5763d3eaf088fd4e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Tax/Api/TaxRuleRepositoryInterfaceTest.php
@@ -0,0 +1,606 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Tax\Api;
+
+use Magento\Framework\Api\FilterBuilder;
+use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Webapi\Model\Rest\Config as HttpConstants;
+
+class TaxRuleRepositoryInterfaceTest extends WebapiAbstract
+{
+    const SERVICE_NAME = "taxTaxRuleRepositoryV1";
+    const SERVICE_VERSION = "V1";
+    const RESOURCE_PATH = "/V1/taxRules";
+
+    /** @var \Magento\Tax\Model\Calculation\Rate[] */
+    private $fixtureTaxRates;
+
+    /** @var \Magento\Tax\Model\ClassModel[] */
+    private $fixtureTaxClasses;
+
+    /** @var \Magento\Tax\Model\Calculation\Rule[] */
+    private $fixtureTaxRules;
+
+    /** @var FilterBuilder */
+    private $filterBuilder;
+
+    /** @var SearchCriteriaBuilder */
+    private $searchCriteriaBuilder;
+
+    /**
+     * Execute per test initialization.
+     */
+    public function setUp()
+    {
+        $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->filterBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+        $objectManager = Bootstrap::getObjectManager();
+
+        $this->searchCriteriaBuilder = $objectManager->create(
+            'Magento\Framework\Api\SearchCriteriaBuilder'
+        );
+        $this->filterBuilder = $objectManager->create(
+            'Magento\Framework\Api\FilterBuilder'
+        );
+
+        /** Initialize tax classes, tax rates and tax rules defined in fixture Magento/Tax/_files/tax_classes.php */
+        $this->getFixtureTaxRates();
+        $this->getFixtureTaxClasses();
+        $this->getFixtureTaxRules();
+    }
+
+    public function tearDown()
+    {
+        $taxRules = $this->getFixtureTaxRules();
+        if (count($taxRules)) {
+            $taxRates = $this->getFixtureTaxRates();
+            $taxClasses = $this->getFixtureTaxClasses();
+            foreach ($taxRules as $taxRule) {
+                $taxRule->delete();
+            }
+            foreach ($taxRates as $taxRate) {
+                $taxRate->delete();
+            }
+            foreach ($taxClasses as $taxClass) {
+                $taxClass->delete();
+            }
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testDeleteTaxRule()
+    {
+        $fixtureRule = $this->getFixtureTaxRules()[0];
+        $taxRuleId = $fixtureRule->getId();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRuleId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'DeleteById',
+            ],
+        ];
+        $requestData = ['ruleId' => $taxRuleId];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertTrue($result);
+        /** Ensure that tax rule was actually removed from DB */
+        /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+        $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+        $this->assertNull($taxRate->load($taxRuleId)->getId(), 'Tax rule was not deleted from DB.');
+    }
+
+    public function testCreateTaxRule()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => HttpConstants::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = [
+            'rule' => [
+                'code' => 'Test Rule ' . microtime(),
+                'position' => 10,
+                'priority' => 5,
+                'customer_tax_class_ids' => [3],
+                'product_tax_class_ids' => [2],
+                'tax_rate_ids' => [1, 2],
+                'calculate_subtotal' => 1,
+            ],
+        ];
+        $taxRuleData = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertArrayHasKey('id', $taxRuleData, "Tax rule ID is expected");
+        $this->assertGreaterThan(0, $taxRuleData['id']);
+        $taxRuleId = $taxRuleData['id'];
+        unset($taxRuleData['id']);
+        $this->assertEquals($requestData['rule'], $taxRuleData, "Tax rule is created with invalid data.");
+        /** Ensure that tax rule was actually created in DB */
+        /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+        $taxRule = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rule');
+        $this->assertEquals($taxRuleId, $taxRule->load($taxRuleId)->getId(), 'Tax rule was not created in DB.');
+        $taxRule->delete();
+    }
+
+    public function testCreateTaxRuleInvalidTaxClassIds()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => HttpConstants::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $requestData = [
+            'rule' => [
+                'code' => 'Test Rule ' . microtime(),
+                'position' => 10,
+                'priority' => 5,
+                'customer_tax_class_ids' => [2],
+                'product_tax_class_ids' => [3],
+                'tax_rate_ids' => [1, 2],
+                'calculate_subtotal' => 1,
+            ],
+        ];
+
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Did not throw expected InputException');
+        } catch (\SoapFault $e) {
+            $this->assertContains('No such entity with customer_tax_class_ids = %fieldValue', $e->getMessage());
+        } catch (\Exception $e) {
+            $this->assertContains('No such entity with customer_tax_class_ids = %fieldValue', $e->getMessage());
+        }
+    }
+
+    public function testCreateTaxRuleExistingCode()
+    {
+        $requestData = [
+            'rule' => [
+                'code' => 'Test Rule ' . microtime(),
+                'position' => 10,
+                'priority' => 5,
+                'customer_tax_class_ids' => [3],
+                'product_tax_class_ids' => [2],
+                'tax_rate_ids' => [1, 2],
+                'calculate_subtotal' => 0,
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $newTaxRuleData = $this->_webApiCall($serviceInfo, $requestData);
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'Code already exists.';
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+
+        // Clean up the new tax rule so it won't affect other tests
+        /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+        $taxRule = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rule');
+        $taxRule->load($newTaxRuleData['id']);
+        $taxRule->delete();
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testGetTaxRule()
+    {
+        $fixtureRule = $this->getFixtureTaxRules()[0];
+        $taxRuleId = $fixtureRule->getId();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRuleId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+
+        $expectedRuleData = [
+            'id' => $taxRuleId,
+            'code' => 'Test Rule Duplicate',
+            'priority' => '0',
+            'position' => '0',
+            'customer_tax_class_ids' => array_values(array_unique($fixtureRule->getCustomerTaxClasses())),
+            'product_tax_class_ids' => array_values(array_unique($fixtureRule->getProductTaxClasses())),
+            'tax_rate_ids' => array_values(array_unique($fixtureRule->getRates())),
+            'calculate_subtotal' => false,
+        ];
+        $requestData = ['ruleId' => $taxRuleId];
+        $result = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($expectedRuleData, $result);
+    }
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testSearchTaxRulesSimple()
+    {
+        // Find rules whose code is 'Test Rule'
+        $filter = $this->filterBuilder->setField('code')
+            ->setValue('Test Rule')
+            ->create();
+
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+
+        $fixtureRule = $this->getFixtureTaxRules()[1];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+
+        /** @var \Magento\Framework\Api\SearchResults $searchResults */
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals(1, $searchResults['total_count']);
+
+        $expectedRuleData = [
+            [
+                'id' => $fixtureRule->getId(),
+                'code' => 'Test Rule',
+                'priority' => 0,
+                'position' => 0,
+                'calculate_subtotal' => 0,
+                'customer_tax_class_ids' => array_values(array_unique($fixtureRule->getCustomerTaxClasses())),
+                'product_tax_class_ids' => array_values(array_unique($fixtureRule->getProductTaxClasses())),
+                'tax_rate_ids' => array_values(array_unique($fixtureRule->getRates())),
+            ],
+        ];
+        $this->assertEquals($expectedRuleData, $searchResults['items']);
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testSearchTaxRulesCodeLike()
+    {
+        // Find rules whose code starts with 'Test Rule'
+        $filter = $this->filterBuilder
+            ->setField('code')
+            ->setValue('Test Rule%')
+            ->setConditionType('like')
+            ->create();
+
+        $sortFilter = $this->filterBuilder
+            ->setField('position')
+            ->setValue(0)
+            ->create();
+
+        $this->searchCriteriaBuilder->addFilter([$filter, $sortFilter]);
+
+        $fixtureRule = $this->getFixtureTaxRules()[1];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+
+        /** @var \Magento\Framework\Api\SearchResults $searchResults */
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+
+        $this->assertEquals(2, $searchResults['total_count']);
+
+        $expectedRuleData = [
+            [
+                'id' => $fixtureRule->getId(),
+                'code' => 'Test Rule',
+                'priority' => 0,
+                'position' => 0,
+                'calculate_subtotal' => 0,
+                'customer_tax_class_ids' => array_values(array_unique($fixtureRule->getCustomerTaxClasses())),
+                'product_tax_class_ids' => array_values(array_unique($fixtureRule->getProductTaxClasses())),
+                'tax_rate_ids' => array_values(array_unique($fixtureRule->getRates())),
+            ],
+            [
+                'id' => $this->getFixtureTaxRules()[0]->getId(),
+                'code' => 'Test Rule Duplicate',
+                'priority' => 0,
+                'position' => 0,
+                'calculate_subtotal' => 0,
+                'customer_tax_class_ids' => array_values(array_unique($fixtureRule->getCustomerTaxClasses())),
+                'product_tax_class_ids' => array_values(array_unique($fixtureRule->getProductTaxClasses())),
+                'tax_rate_ids' => array_values(array_unique($fixtureRule->getRates()))
+            ],
+        ];
+        $this->assertEquals($expectedRuleData, $searchResults['items']);
+    }
+
+    public function testGetTaxRuleNotExist()
+    {
+        $taxRuleId = 37865;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . "/$taxRuleId",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Get',
+            ],
+        ];
+        $requestData = ['ruleId' => $taxRuleId];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testUpdateTaxRule()
+    {
+        $fixtureRule = $this->getFixtureTaxRules()[0];
+        $requestData = [
+            'rule' => [
+                'id' => $fixtureRule->getId(),
+                'code' => 'Test Rule ' . microtime(),
+                'position' => 10,
+                'priority' => 5,
+                'customer_tax_class_ids' => [3],
+                'product_tax_class_ids' => [2],
+                'tax_rate_ids' => [1, 2],
+                'calculate_subtotal' => 1,
+            ],
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        $this->_webApiCall($serviceInfo, $requestData);
+        $expectedRuleData = $requestData['rule'];
+        /** Ensure that tax rule was actually updated in DB */
+        /** @var \Magento\Tax\Model\Calculation $taxCalculation */
+        $taxCalculation = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation');
+        /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+        $taxRule = Bootstrap::getObjectManager()->create(
+            'Magento\Tax\Model\Calculation\Rule',
+            ['calculation' => $taxCalculation]
+        );
+        $taxRuleModel = $taxRule->load($fixtureRule->getId());
+        $this->assertEquals($expectedRuleData['id'], $taxRuleModel->getId(), 'Tax rule was not updated in DB.');
+        $this->assertEquals(
+            $expectedRuleData['code'],
+            $taxRuleModel->getCode(),
+            'Tax rule code was updated incorrectly.'
+        );
+        $this->assertEquals(
+            $expectedRuleData['position'],
+            $taxRuleModel->getPosition(),
+            'Tax rule sort order was updated incorrectly.'
+        );
+        $this->assertEquals(
+            $expectedRuleData['priority'],
+            $taxRuleModel->getPriority(),
+            'Tax rule priority was updated incorrectly.'
+        );
+        $this->assertEquals(
+            $expectedRuleData['customer_tax_class_ids'],
+            array_values(array_unique($taxRuleModel->getCustomerTaxClasses())),
+            'Customer Tax classes were updated incorrectly'
+        );
+        $this->assertEquals(
+            $expectedRuleData['product_tax_class_ids'],
+            array_values(array_unique($taxRuleModel->getProductTaxClasses())),
+            'Product Tax classes were updated incorrectly.'
+        );
+        $this->assertEquals(
+            $expectedRuleData['tax_rate_ids'],
+            array_values(array_unique($taxRuleModel->getRates())),
+            'Tax rates were updated incorrectly.'
+        );
+    }
+    public function testUpdateTaxRuleNotExisting()
+    {
+        $requestData = [
+            'rule' => [
+                'id' => 12345,
+                'code' => 'Test Rule ' . microtime(),
+                'position' => 10,
+                'priority' => 5,
+                'customer_tax_class_ids' => [3],
+                'product_tax_class_ids' => [2],
+                'tax_rate_ids' => [1, 2],
+            ],
+        ];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'Save',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+            $this->fail('Expected exception was not raised');
+        } catch (\Exception $e) {
+            $expectedMessage = 'No such entity with %fieldName = %fieldValue';
+
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Exception does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     * @magentoApiDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testSearchTaxRule()
+    {
+        $fixtureRule = $this->getFixtureTaxRules()[0];
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => self::RESOURCE_PATH . '/search',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => [
+                'service' => self::SERVICE_NAME,
+                'serviceVersion' => self::SERVICE_VERSION,
+                'operation' => self::SERVICE_NAME . 'GetList',
+            ],
+        ];
+
+        $filter = $this->filterBuilder->setField('code')
+            ->setValue($fixtureRule->getCode())
+            ->create();
+        $this->searchCriteriaBuilder->addFilter([$filter]);
+        $searchData = $this->searchCriteriaBuilder->create()->__toArray();
+        $requestData = ['searchCriteria' => $searchData];
+        $searchResults = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(1, $searchResults['total_count']);
+        $this->assertEquals($fixtureRule->getId(), $searchResults['items'][0]["id"]);
+        $this->assertEquals($fixtureRule->getCode(), $searchResults['items'][0]['code']);
+    }
+
+    /**
+     * Get tax rates created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\Calculation\Rate[]
+     */
+    private function getFixtureTaxRates()
+    {
+        if (is_null($this->fixtureTaxRates)) {
+            $this->fixtureTaxRates = [];
+            if ($this->getFixtureTaxRules()) {
+                $taxRateIds = (array)$this->getFixtureTaxRules()[0]->getRates();
+                foreach ($taxRateIds as $taxRateId) {
+                    /** @var \Magento\Tax\Model\Calculation\Rate $taxRate */
+                    $taxRate = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rate');
+                    $this->fixtureTaxRates[] = $taxRate->load($taxRateId);
+                }
+            }
+        }
+        return $this->fixtureTaxRates;
+    }
+
+    /**
+     * Get tax classes created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\ClassModel[]
+     */
+    private function getFixtureTaxClasses()
+    {
+        if (is_null($this->fixtureTaxClasses)) {
+            $this->fixtureTaxClasses = [];
+            if ($this->getFixtureTaxRules()) {
+                $taxClassIds = array_merge(
+                    (array)$this->getFixtureTaxRules()[0]->getCustomerTaxClasses(),
+                    (array)$this->getFixtureTaxRules()[0]->getProductTaxClasses()
+                );
+                foreach ($taxClassIds as $taxClassId) {
+                    /** @var \Magento\Tax\Model\ClassModel $taxClass */
+                    $taxClass = Bootstrap::getObjectManager()->create('Magento\Tax\Model\ClassModel');
+                    $this->fixtureTaxClasses[] = $taxClass->load($taxClassId);
+                }
+            }
+        }
+        return $this->fixtureTaxClasses;
+    }
+
+    /**
+     * Get tax rule created in Magento\Tax\_files\tax_classes.php
+     *
+     * @return \Magento\Tax\Model\Calculation\Rule[]
+     */
+    private function getFixtureTaxRules()
+    {
+        if (is_null($this->fixtureTaxRules)) {
+            $this->fixtureTaxRules = [];
+            $taxRuleCodes = ['Test Rule Duplicate', 'Test Rule'];
+            foreach ($taxRuleCodes as $taxRuleCode) {
+                /** @var \Magento\Tax\Model\Calculation\Rule $taxRule */
+                $taxRule = Bootstrap::getObjectManager()->create('Magento\Tax\Model\Calculation\Rule');
+                $taxRule->load($taxRuleCode, 'code');
+                if ($taxRule->getId()) {
+                    $this->fixtureTaxRules[] = $taxRule;
+                }
+            }
+        }
+        return $this->fixtureTaxRules;
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Authentication/RestTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Authentication/RestTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f8bd45445a6e5c43b3969d391bf47920e3245a6
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Authentication/RestTest.php
@@ -0,0 +1,203 @@
+<?php
+/**
+ * Test authentication mechanisms in REST.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Authentication;
+
+/**
+ * @magentoApiDataFixture consumerFixture
+ */
+class RestTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /** @var \Magento\TestFramework\Authentication\Rest\OauthClient[] */
+    protected $_oAuthClients = [];
+
+    /** @var \Magento\Integration\Model\Oauth\Consumer */
+    protected static $_consumer;
+
+    /** @var \Magento\Integration\Model\Oauth\Token */
+    protected static $_token;
+
+    /** @var string */
+    protected static $_consumerKey;
+
+    /** @var string */
+    protected static $_consumerSecret;
+
+    /** @var string */
+    protected static $_verifier;
+
+    protected function setUp()
+    {
+        $this->_markTestAsRestOnly();
+        parent::setUp();
+    }
+
+    /**
+     * Create a consumer
+     */
+    public static function consumerFixture($date = null)
+    {
+        /** Clear the credentials because during the fixture generation, any previous credentials are invalidated */
+        \Magento\TestFramework\Authentication\OauthHelper::clearApiAccessCredentials();
+
+        $consumerCredentials = \Magento\TestFramework\Authentication\OauthHelper::getConsumerCredentials($date);
+        self::$_consumerKey = $consumerCredentials['key'];
+        self::$_consumerSecret = $consumerCredentials['secret'];
+        self::$_verifier = $consumerCredentials['verifier'];
+        self::$_consumer = $consumerCredentials['consumer'];
+        self::$_token = $consumerCredentials['token'];
+    }
+
+    protected function tearDown()
+    {
+        parent::tearDown();
+        $this->_oAuthClients = [];
+        if (isset(self::$_consumer)) {
+            self::$_consumer->delete();
+            self::$_token->delete();
+        }
+    }
+
+    public function testGetRequestToken()
+    {
+        /** @var $oAuthClient \Magento\TestFramework\Authentication\Rest\OauthClient */
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $requestToken = $oAuthClient->requestRequestToken();
+
+        $this->assertNotEmpty($requestToken->getRequestToken(), "Request token value is not set");
+        $this->assertNotEmpty($requestToken->getRequestTokenSecret(), "Request token secret is not set");
+
+        $this->assertEquals(
+            \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN,
+            strlen($requestToken->getRequestToken()),
+            "Request token value length should be " . \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN
+        );
+        $this->assertEquals(
+            \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN_SECRET,
+            strlen($requestToken->getRequestTokenSecret()),
+            "Request token secret length should be " . \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN_SECRET
+        );
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testGetRequestTokenExpiredConsumer()
+    {
+        $this::consumerFixture('2012-01-01 00:00:00');
+        /** @var $oAuthClient \Magento\TestFramework\Authentication\Rest\OauthClient */
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $oAuthClient->requestRequestToken();
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testGetRequestTokenInvalidConsumerKey()
+    {
+        $oAuthClient = $this->_getOauthClient('invalid_key', self::$_consumerSecret);
+        $oAuthClient->requestRequestToken();
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testGetRequestTokenInvalidConsumerSecret()
+    {
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, 'invalid_secret');
+        $oAuthClient->requestRequestToken();
+    }
+
+    public function testGetAccessToken()
+    {
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $requestToken = $oAuthClient->requestRequestToken();
+        $accessToken = $oAuthClient->requestAccessToken(
+            $requestToken->getRequestToken(),
+            self::$_verifier,
+            $requestToken->getRequestTokenSecret()
+        );
+        $this->assertNotEmpty($accessToken->getAccessToken(), "Access token value is not set.");
+        $this->assertNotEmpty($accessToken->getAccessTokenSecret(), "Access token secret is not set.");
+
+        $this->assertEquals(
+            \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN,
+            strlen($accessToken->getAccessToken()),
+            "Access token value length should be " . \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN
+        );
+        $this->assertEquals(
+            \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN_SECRET,
+            strlen($accessToken->getAccessTokenSecret()),
+            "Access token secret length should be " . \Magento\Framework\Oauth\Helper\Oauth::LENGTH_TOKEN_SECRET
+        );
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testGetAccessTokenInvalidVerifier()
+    {
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $requestToken = $oAuthClient->requestRequestToken();
+        $oAuthClient->requestAccessToken(
+            $requestToken->getRequestToken(),
+            'invalid verifier',
+            $requestToken->getRequestTokenSecret()
+        );
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testGetAccessTokenConsumerMismatch()
+    {
+        $oAuthClientA = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $requestTokenA = $oAuthClientA->requestRequestToken();
+        $oauthVerifierA = self::$_verifier;
+
+        self::consumerFixture();
+        $oAuthClientB = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+
+        $oAuthClientB->requestAccessToken(
+            $requestTokenA->getRequestToken(),
+            $oauthVerifierA,
+            $requestTokenA->getRequestTokenSecret()
+        );
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage HTTP/1.1 401
+     */
+    public function testAccessApiInvalidAccessToken()
+    {
+        $oAuthClient = $this->_getOauthClient(self::$_consumerKey, self::$_consumerSecret);
+        $requestToken = $oAuthClient->requestRequestToken();
+        $accessToken = $oAuthClient->requestAccessToken(
+            $requestToken->getRequestToken(),
+            self::$_verifier,
+            $requestToken->getRequestTokenSecret()
+        );
+        $accessToken->setAccessToken('invalid');
+        $oAuthClient->validateAccessToken($accessToken);
+    }
+
+    protected function _getOauthClient($consumerKey, $consumerSecret)
+    {
+        if (!isset($this->_oAuthClients[$consumerKey])) {
+            $credentials = new \OAuth\Common\Consumer\Credentials($consumerKey, $consumerSecret, TESTS_BASE_URL);
+            $this->_oAuthClients[$consumerKey] = new \Magento\TestFramework\Authentication\Rest\OauthClient(
+                $credentials
+            );
+        }
+        return $this->_oAuthClients[$consumerKey];
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationMSCTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationMSCTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b1f33148d999c81ac87d6444edf593408cbe1a1
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationMSCTest.php
@@ -0,0 +1,244 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi\DataObjectSerialization;
+
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestModuleMSC\Api\Data\ItemDataBuilder;
+use Magento\Webapi\Controller\Rest\Response\DataObjectConverter;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationMSCTest.php
+ * Class to test if custom attributes are serialized correctly for the new Module Service Contract approach
+ */
+class CustomAttributeSerializationMSCTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+    /**
+     * @var string
+     */
+    protected $_soapService = 'testModuleMSCAllSoapAndRest';
+
+    /**
+     * @var ItemDataBuilder
+     */
+    protected $itemDataBuilder;
+
+    /**
+     * @var \Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectDataBuilder
+     */
+    protected $customAttributeNestedDataObjectDataBuilder;
+
+    /**
+     * @var \Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectDataBuilder
+     */
+    protected $customAttributeDataObjectDataBuilder;
+
+    /**
+     * @var DataObjectProcessor $dataObjectProcessor
+     */
+    protected $dataObjectProcessor;
+
+    /**
+     * @var DataObjectConverter $dataObjectConverter
+     */
+    protected $dataObjectConverter;
+
+    /**
+     * Set up custom attribute related data objects
+     */
+    protected function setUp()
+    {
+        $this->markTestSkipped('This test become irrelevant according to new API Contract');
+        $this->_version = 'V1';
+        $this->_soapService = 'testModuleMSCAllSoapAndRestV1';
+        $this->_restResourcePath = "/{$this->_version}/testmoduleMSC/";
+
+        $this->itemDataBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModuleMSC\Api\Data\ItemDataBuilder'
+        );
+
+        $this->customAttributeNestedDataObjectDataBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectDataBuilder'
+        );
+
+        $this->customAttributeDataObjectDataBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectDataBuilder'
+        );
+
+        $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Reflection\DataObjectProcessor'
+        );
+
+        $this->dataObjectConverter = Bootstrap::getObjectManager()->create(
+            'Magento\Webapi\Controller\Rest\Response\DataObjectConverter'
+        );
+    }
+
+    public function testSimpleAndNonExistentCustomAttributes()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = [
+            'item_id' => 1,
+            'name' => 'testProductAnyType',
+            'custom_attributes' => [
+                    'non_existent' => [
+                            'attribute_code' => 'non_existent',
+                            'value' => 'test',
+                        ],
+                    'custom_attribute_string' => [
+                            'attribute_code' => 'custom_attribute_string',
+                            'value' => 'someStringValue',
+                        ],
+                ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        //The non_existent custom attribute should be dropped since its not a defined custom attribute
+        $expectedResponse = [
+            'item_id' => 1,
+            'name' => 'testProductAnyType',
+            'custom_attributes' => [
+                    [
+                        'attribute_code' => 'custom_attribute_string',
+                        'value' => 'someStringValue',
+                    ],
+                ],
+        ];
+
+        //\Magento\TestModuleMSC\Api\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testDataObjectCustomAttributes()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $customAttributeDataObject = $this->customAttributeDataObjectDataBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemDataBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = $this->dataObjectProcessor->buildOutputDataArray($item, get_class($item));
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModuleMSC\Api\AllSoapAndRestInterface',
+            'itemAnyType'
+        );
+        //\Magento\TestModuleMSC\Api\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testDataObjectCustomAttributesPreconfiguredItem()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemPreconfigured',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'GetPreconfiguredItem'],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, []);
+
+        $customAttributeDataObject = $this->customAttributeDataObjectDataBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemDataBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModuleMSC\Api\AllSoapAndRestInterface',
+            'getPreconfiguredItem'
+        );
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testNestedDataObjectCustomAttributes()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $customAttributeNestedDataObject = $this->customAttributeNestedDataObjectDataBuilder
+            ->setName('nestedNameValue')
+            ->create();
+
+        $customAttributeDataObject = $this->customAttributeDataObjectDataBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_nested', $customAttributeNestedDataObject)
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemDataBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = $this->dataObjectProcessor->buildOutputDataArray(
+            $item,
+            '\Magento\TestModuleMSC\Api\Data\ItemInterface'
+        );
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModuleMSC\Api\AllSoapAndRestInterface',
+            'itemAnyType'
+        );
+        //\Magento\TestModuleMSC\Api\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4baca07992c41b68ac509b10a5d646550b414d06
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/CustomAttributeSerializationTest.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+/**
+ * Class to test if custom attributes are serialized correctly
+ */
+namespace Magento\Webapi\DataObjectSerialization;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestModule1\Service\V1\Entity\ItemBuilder;
+use Magento\Webapi\Controller\Rest\Response\DataObjectConverter;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class CustomAttributeSerializationTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+    /**
+     * @var string
+     */
+    protected $_soapService = 'testModule1AllSoapAndRest';
+
+    /**
+     * @var ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @var \Magento\TestModule1\Service\V1\Entity\CustomAttributeNestedDataObjectBuilder
+     */
+    protected $customAttributeNestedDataObjectBuilder;
+
+    /**
+     * @var \Magento\TestModule1\Service\V1\Entity\CustomAttributeDataObjectBuilder
+     */
+    protected $customAttributeDataObjectBuilder;
+
+    /**
+     * @var DataObjectConverter $dataObjectConverter
+     */
+    protected $dataObjectConverter;
+
+    /**
+     * Set up custom attribute related data objects
+     */
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_soapService = 'testModule1AllSoapAndRestV1';
+        $this->_restResourcePath = "/{$this->_version}/testmodule1/";
+
+        $this->itemBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModule1\Service\V1\Entity\ItemBuilder'
+        );
+
+        $this->customAttributeNestedDataObjectBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModule1\Service\V1\Entity\CustomAttributeNestedDataObjectBuilder'
+        );
+
+        $this->customAttributeDataObjectBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModule1\Service\V1\Entity\CustomAttributeDataObjectBuilder'
+        );
+
+        $this->dataObjectConverter = Bootstrap::getObjectManager()->create(
+            'Magento\Webapi\Controller\Rest\Response\DataObjectConverter'
+        );
+    }
+
+    public function testSimpleAndNonExistentCustomAttributes()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = [
+            'item_id' => 1,
+            'name' => 'testProductAnyType',
+            'custom_attributes' => [
+                    'non_existent' => [
+                            'attribute_code' => 'non_existent',
+                            'value' => 'test',
+                        ],
+                    'custom_attribute_string' => [
+                            'attribute_code' => 'custom_attribute_string',
+                            'value' => 'someStringValue',
+                        ],
+                ],
+        ];
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        //The non_existent custom attribute should be dropped since its not a defined custom attribute
+        $expectedResponse = [
+            'item_id' => 1,
+            'name' => 'testProductAnyType',
+            'custom_attributes' => [
+                    [
+                        'attribute_code' => 'custom_attribute_string',
+                        'value' => 'someStringValue',
+                    ],
+                ],
+        ];
+
+        //\Magento\TestModule1\Service\V1\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testDataObjectCustomAttributes()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $customAttributeDataObject = $this->customAttributeDataObjectBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = $item->__toArray();
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModule1\Service\V1\AllSoapAndRestInterface',
+            'itemAnyType'
+        );
+        //\Magento\TestModule1\Service\V1\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testDataObjectCustomAttributesPreconfiguredItem()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemPreconfigured',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'GetPreconfiguredItem'],
+        ];
+
+        $result = $this->_webApiCall($serviceInfo, []);
+
+        $customAttributeDataObject = $this->customAttributeDataObjectBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModule1\Service\V1\AllSoapAndRestInterface',
+            'getPreconfiguredItem'
+        );
+        $this->assertEquals($expectedResponse, $result);
+    }
+
+    public function testNestedDataObjectCustomAttributes()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $customAttributeNestedDataObject = $this->customAttributeNestedDataObjectBuilder
+            ->setName('nestedNameValue')
+            ->create();
+
+        $customAttributeDataObject = $this->customAttributeDataObjectBuilder
+            ->setName('nameValue')
+            ->setCustomAttribute('custom_attribute_nested', $customAttributeNestedDataObject)
+            ->setCustomAttribute('custom_attribute_int', 1)
+            ->create();
+
+        $item = $this->itemBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttribute('custom_attribute_data_object', $customAttributeDataObject)
+            ->setCustomAttribute('custom_attribute_string', 'someStringValue')
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = $item->__toArray();
+        $result = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        $expectedResponse = $this->dataObjectConverter->processServiceOutput(
+            $item,
+            '\Magento\TestModule1\Service\V1\AllSoapAndRestInterface',
+            'itemAnyType'
+        );
+        //\Magento\TestModule1\Service\V1\AllSoapAndRest::itemAnyType just return the input data back as response
+        $this->assertEquals($expectedResponse, $result);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/ServiceSerializationTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/ServiceSerializationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce7aa7ea452fcb1622e2963a514b182c17b66a31
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/DataObjectSerialization/ServiceSerializationTest.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\DataObjectSerialization;
+
+class ServiceSerializationTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+
+    protected function setUp()
+    {
+        $this->_markTestAsRestOnly();
+        $this->_version = 'V1';
+        $this->_restResourcePath = "/{$this->_version}/testmodule4/";
+    }
+
+    /**
+     *  Test simple request data
+     */
+    public function testGetServiceCall()
+    {
+        $itemId = 1;
+        $name = 'Test';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, []);
+        $this->assertEquals($itemId, $item['entity_id'], 'id field returned incorrectly');
+        $this->assertEquals($name, $item['name'], 'name field returned incorrectly');
+    }
+
+    /**
+     *  Test multiple params with Data Object
+     */
+    public function testUpdateServiceCall()
+    {
+        $itemId = 1;
+        $name = 'Test';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, ['request' => ['name' => $name]]);
+        $this->assertEquals($itemId, $item['entity_id'], 'id field returned incorrectly');
+        $this->assertEquals($name, $item['name'], 'name field returned incorrectly');
+    }
+
+    /**
+     *  Test nested Data Object
+     */
+    public function testNestedDataObjectCall()
+    {
+        $itemId = 1;
+        $name = 'Test';
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId . '/nested',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, ['request' => ['details' => ['name' => $name]]]);
+        $this->assertEquals($itemId, $item['entity_id'], 'id field returned incorrectly');
+        $this->assertEquals($name, $item['name'], 'name field returned incorrectly');
+    }
+
+    public function testScalarResponse()
+    {
+        $id = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "{$this->_restResourcePath}scalar/{$id}",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+        $this->assertEquals($id, $this->_webApiCall($serviceInfo), 'Scalar service output is serialized incorrectly.');
+    }
+
+    public function testExtensibleCall()
+    {
+        $id = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "{$this->_restResourcePath}extensibleDataObject/{$id}",
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST,
+            ],
+        ];
+
+        $name = 'Magento';
+        $requestData = [
+          'name' => $name,
+        ];
+        $item = $this->_webApiCall($serviceInfo, ['request' => $requestData]);
+        $this->assertEquals($id, $item['entity_id'], 'id field returned incorrectly');
+        $this->assertEquals($name, $item['name'], 'name field returned incorrectly');
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..06a701a2ec6f117789b75b9dc150732c1ec4e6db
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/DeserializationTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi;
+
+use Magento\TestFramework\TestCase\Webapi\Adapter\Rest\CurlClient;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class DeserializationTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_restResourcePath = "/{$this->_version}/TestModule5/";
+    }
+
+    /**
+     *  Test POST request with empty body
+     */
+    public function testPostRequestWithEmptyBody()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath,
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+        ];
+        $expectedMessage = '{"message":"%fieldName is a required field.","parameters":{"fieldName":"item"}}';
+        try {
+            $this->_webApiCall($serviceInfo, CurlClient::EMPTY_REQUEST_BODY);
+        } catch (\Exception $e) {
+            $this->assertEquals(\Magento\Webapi\Exception::HTTP_BAD_REQUEST, $e->getCode());
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Response does not contain expected message."
+            );
+        }
+    }
+
+    /**
+     *  Test PUT request with empty body
+     */
+    public function testPutRequestWithEmptyBody()
+    {
+        $this->_markTestAsRestOnly();
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $expectedMessage = '{"message":"%fieldName is a required field.","parameters":{"fieldName":"entityItem"}}';
+        try {
+            $this->_webApiCall($serviceInfo, CurlClient::EMPTY_REQUEST_BODY);
+        } catch (\Exception $e) {
+            $this->assertEquals(\Magento\Webapi\Exception::HTTP_BAD_REQUEST, $e->getCode());
+            $this->assertContains(
+                $expectedMessage,
+                $e->getMessage(),
+                "Response does not contain expected message."
+            );
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/PartialResponseTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/PartialResponseTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..36b79d9157bf635865c040218576b9339ccb49fb
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/PartialResponseTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi;
+
+use Magento\Customer\Api\AccountManagementTest;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\Helper\Customer as CustomerHelper;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class PartialResponseTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /** @var CustomerHelper */
+    protected $customerHelper;
+
+    /** @var string */
+    protected $customerData;
+
+    protected function setUp()
+    {
+        $this->_markTestAsRestOnly('Partial response functionality available in REST mode only.');
+
+        $this->customerHelper = Bootstrap::getObjectManager()
+            ->get('Magento\TestFramework\Helper\Customer');
+
+        $this->customerData = $this->customerHelper->createSampleCustomer();
+    }
+
+    public function testCustomerWithEmailFilter()
+    {
+        $filter = 'email';
+        $expected = ['email' => $this->customerData['email']];
+        $result = $this->_getCustomerWithFilter($filter, $this->customerData['id']);
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testCustomerWithEmailAndAddressFilter()
+    {
+        $filter = 'email,addresses[city]';
+        $expected = [
+            'email' => $this->customerData['email'],
+            'addresses' => [
+                ['city' => CustomerHelper::ADDRESS_CITY1],
+                ['city' => CustomerHelper::ADDRESS_CITY2],
+            ],
+        ];
+        $result = $this->_getCustomerWithFilter($filter, $this->customerData['id']);
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testCustomerWithNestedAddressFilter()
+    {
+        $filter = 'addresses[region[region_code]]';
+        $expected = [
+            'addresses' => [
+                ['region' => ['region_code' => CustomerHelper::ADDRESS_REGION_CODE1]],
+                ['region' => ['region_code' => CustomerHelper::ADDRESS_REGION_CODE2]],
+            ],
+        ];
+        $result = $this->_getCustomerWithFilter($filter, $this->customerData['id']);
+        $this->assertEquals($expected, $result);
+    }
+
+    public function testCustomerInvalidFilter()
+    {
+        // Invalid filter should return an empty result
+        $result = $this->_getCustomerWithFilter('invalid', $this->customerData['id']);
+        $this->assertEmpty($result);
+    }
+
+    public function testFilterForCustomerApiWithSimpleResponse()
+    {
+        $result = $this->_getCustomerWithFilter('customers', $this->customerData['id'], '/permissions/readonly');
+        // assert if filter is ignored and a normal response is returned
+        $this->assertFalse($result);
+    }
+
+    protected function _getCustomerWithFilter($filter, $customerId, $path = '')
+    {
+        $resourcePath = sprintf(
+            '%s/%d%s?fields=%s',
+            AccountManagementTest::RESOURCE_PATH,
+            $customerId,
+            $path,
+            $filter
+        );
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $resourcePath,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+
+        return $this->_webApiCall($serviceInfo);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php
new file mode 100644
index 0000000000000000000000000000000000000000..5312762a3ae8634e5d0a98a1fcebe27636160f4f
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Routing;
+
+use Magento\Framework\Exception\AuthorizationException;
+use Magento\Webapi\Exception as WebapiException;
+
+/**
+ * Base class for all Service based routing tests
+ */
+abstract class BaseService extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * Check a particular adapter and assert unauthorized access
+     *
+     * @param array      $serviceInfo
+     * @param array|null $requestData
+     */
+    protected function assertUnauthorizedException($serviceInfo, $requestData = null)
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->_assertSoapException($serviceInfo, $requestData, 'Consumer is not authorized to access %resources');
+        } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+            $this->_assertRestUnauthorizedException($serviceInfo, $requestData);
+        }
+    }
+
+    /**
+     * Invoke the REST api and assert access is unauthorized
+     *
+     * @param array      $serviceInfo
+     * @param array|null $requestData
+     */
+    protected function _assertRestUnauthorizedException($serviceInfo, $requestData = null)
+    {
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $this->assertContains(
+                '{"message":"' . AuthorizationException::NOT_AUTHORIZED . '"',
+                $e->getMessage(),
+                sprintf(
+                    'REST routing did not fail as expected for the method "%s" of service "%s"',
+                    $serviceInfo['rest']['httpMethod'],
+                    $serviceInfo['rest']['resourcePath']
+                )
+            );
+            $this->assertEquals(WebapiException::HTTP_UNAUTHORIZED, $e->getCode());
+        }
+    }
+
+    /**
+     * Check a particular adapter and assert the exception
+     *
+     * @param array      $serviceInfo
+     * @param array|null $requestData
+     */
+    protected function _assertNoRouteOrOperationException($serviceInfo, $requestData = null)
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->_assertSoapException($serviceInfo, $requestData);
+        } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+            $this->_assertNoRestRouteException($serviceInfo, $requestData);
+        }
+    }
+
+    /**
+     * Invoke the REST api and assert for test cases that no such REST route exist
+     *
+     * @param array      $serviceInfo
+     * @param array|null $requestData
+     */
+    protected function _assertNoRestRouteException($serviceInfo, $requestData = null)
+    {
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            $error = json_decode($e->getMessage(), true);
+            $this->assertEquals('Request does not match any route.', $error['message']);
+            $this->assertEquals(WebapiException::HTTP_NOT_FOUND, $e->getCode());
+        }
+    }
+
+    /**
+     * Invoke the SOAP api and assert for the NoWebApiXmlTestTest test cases that no such SOAP route exists
+     *
+     * @param array      $serviceInfo
+     * @param array|null $requestData
+     * @param string     $expectedMessage
+     */
+    protected function _assertSoapException($serviceInfo, $requestData = null, $expectedMessage = '')
+    {
+        try {
+            $this->_webApiCall($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            if (get_class($e) !== 'SoapFault') {
+                $this->fail(
+                    sprintf(
+                        'Expected SoapFault exception not generated for Service - "%s" and Operation - "%s"',
+                        $serviceInfo['soap']['service'],
+                        $serviceInfo['soap']['operation']
+                    )
+                );
+            }
+
+            if ($expectedMessage) {
+                $this->assertEquals($expectedMessage, $e->getMessage());
+            }
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/CoreRoutingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/CoreRoutingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1959e4f59fc9a54e46a4ad472fc8916471f2f4e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/CoreRoutingTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+/**
+ * Class to test Core Web API routing
+ */
+namespace Magento\Webapi\Routing;
+
+class CoreRoutingTest extends \Magento\Webapi\Routing\BaseService
+{
+    public function testBasicRoutingExplicitPath()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/testmodule1/' . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'testModule1AllSoapAndRestV1',
+                'operation' => 'testModule1AllSoapAndRestV1Item',
+            ],
+        ];
+        $requestData = ['itemId' => $itemId];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals('testProduct1', $item['name'], "Item was retrieved unsuccessfully");
+    }
+
+    public function testDisabledIntegrationAuthorizationException()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/testmodule1/' . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => 'testModule1AllSoapAndRestV1',
+                'operation' => 'testModule1AllSoapAndRestV1Item',
+            ],
+        ];
+        $requestData = ['itemId' => $itemId];
+
+        /** Disable integration associated with active OAuth credentials. */
+        $credentials = \Magento\TestFramework\Authentication\OauthHelper::getApiAccessCredentials();
+        /** @var \Magento\Integration\Model\Integration $integration */
+        $integration = $credentials['integration'];
+        $originalStatus = $integration->getStatus();
+        $integration->setStatus(\Magento\Integration\Model\Integration::STATUS_INACTIVE)->save();
+
+        try {
+            $this->assertUnauthorizedException($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            /** Restore original status of integration associated with active OAuth credentials */
+            $integration->setStatus($originalStatus)->save();
+            throw $e;
+        }
+        $integration->setStatus($originalStatus)->save();
+    }
+
+    public function testExceptionSoapInternalError()
+    {
+        $this->_markTestAsSoapOnly();
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'testModule3ErrorV1',
+                'operation' => 'testModule3ErrorV1ServiceException',
+            ],
+        ];
+        $this->setExpectedException('SoapFault', 'Generic service exception');
+        $this->_webApiCall($serviceInfo);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/GettersTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/GettersTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5dfc7fb4a6e240be896190d2319dfb2c943e6299
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/GettersTest.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Routing;
+
+use Magento\TestModule5\Service\V1\Entity\AllSoapAndRest;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class GettersTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+
+    /**
+     * @var string
+     */
+    protected $_soapService = 'testModule5AllSoapAndRest';
+
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_soapService = "testModule5AllSoapAndRest{$this->_version}";
+        $this->_restResourcePath = "/{$this->_version}/TestModule5/";
+    }
+
+    public function testGetters()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => $this->_soapService,
+                'operation' => $this->_soapService . 'Item',
+            ],
+        ];
+        $requestData = [AllSoapAndRest::ID => $itemId];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($itemId, $item[AllSoapAndRest::ID], 'Item was retrieved unsuccessfully');
+        $isEnabled = isset($item[AllSoapAndRest::ENABLED]) && $item[AllSoapAndRest::ENABLED] === true;
+        $this->assertTrue($isEnabled, 'Getter with "is" prefix is processed incorrectly.');
+        $hasOrder = isset($item[AllSoapAndRest::HAS_ORDERS]) && $item[AllSoapAndRest::HAS_ORDERS] === true;
+        $this->assertTrue($hasOrder, 'Getter with "has" prefix is processed incorrectly.');
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/NoWebApiXmlTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/NoWebApiXmlTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..819429fb00302902ff55d6960ff64b5ee9218705
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/NoWebApiXmlTest.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Routing;
+
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class to test routing with a service that has no webapi.xml
+ */
+class NoWebApiXmlTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    private $_version;
+
+    /**
+     * @var string
+     */
+    private $_restResourcePath;
+
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_restResourcePath = "/{$this->_version}/testModule2NoWebApiXml/";
+    }
+
+    /**
+     *  Test get item
+     */
+    public function testItem()
+    {
+        $this->_markTestAsRestOnly();
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        $requestData = ['id' => $itemId];
+        $this->_assertNoRestRouteException($serviceInfo, $requestData);
+    }
+
+    /**
+     * Test fetching all items
+     */
+    public function testItems()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => ['resourcePath' => $this->_restResourcePath, 'httpMethod' => RestConfig::HTTP_METHOD_GET],
+        ];
+        $this->_assertNoRestRouteException($serviceInfo);
+    }
+
+    /**
+     *  Test create item
+     */
+    public function testCreate()
+    {
+        $this->_markTestAsRestOnly();
+        $createdItemName = 'createdItemName';
+        $serviceInfo = [
+            'rest' => ['resourcePath' => $this->_restResourcePath, 'httpMethod' => RestConfig::HTTP_METHOD_POST],
+        ];
+        $requestData = ['name' => $createdItemName];
+        $this->_assertNoRestRouteException($serviceInfo, $requestData);
+    }
+
+    /**
+     *  Test update item
+     */
+    public function testUpdate()
+    {
+        $this->_markTestAsRestOnly();
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $requestData = ['id' => $itemId];
+        $this->_assertNoRestRouteException($serviceInfo, $requestData);
+    }
+
+    /**
+     *  Test remove item
+     */
+    public function testRemove()
+    {
+        $this->_markTestAsRestOnly();
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+        ];
+        $requestData = ['id' => $itemId];
+        $this->_assertNoRestRouteException($serviceInfo, $requestData);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RequestIdOverrideTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RequestIdOverrideTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ed32b0349fe1a14417e294732777634d0553431
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RequestIdOverrideTest.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi\Routing;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+/**
+ * Class to test overriding request body identifier property with id passed in url path parameter
+ *
+ * Refer to \Magento\Webapi\Controller\Rest\Request::overrideRequestBodyIdWithPathParam
+ */
+class RequestIdOverrideTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+
+    /**
+     * @var \Magento\TestModule5\Service\V1\Entity\AllSoapAndRestBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * @var string
+     */
+    protected $_soapService = 'testModule5AllSoapAndRest';
+
+    protected function setUp()
+    {
+        $this->_markTestAsRestOnly('Request Id overriding is a REST based feature.');
+        $this->_version = 'V1';
+        $this->_restResourcePath = "/{$this->_version}/TestModule5/";
+        $this->itemBuilder = Bootstrap::getObjectManager()
+            ->create('Magento\TestModule5\Service\V1\Entity\AllSoapAndRestBuilder');
+    }
+
+    public function testOverride()
+    {
+        $itemId = 1;
+        $incorrectItemId = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $item = $this->itemBuilder
+            ->setEntityId($incorrectItemId)
+            ->setName('test')
+            ->create();
+        $requestData = ['entityItem' => $item->__toArray()];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $itemId,
+            $item[\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest::ID],
+            'Identifier overriding failed.'
+        );
+    }
+
+    public function testOverrideNested()
+    {
+        $firstItemId = 1;
+        $secondItemId = 11;
+        $incorrectItemId = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $firstItemId . '/nestedResource/' . $secondItemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $item = $this->itemBuilder
+            ->setEntityId($incorrectItemId)
+            ->setName('test')
+            ->create();
+        $requestData = ['entityItem' => $item->__toArray()];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $secondItemId,
+            $item[\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest::ID],
+            'Identifier overriding failed for nested resource request.'
+        );
+    }
+
+    public function testOverrideAdd()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $item = $this->itemBuilder
+            ->setName('test')
+            ->create();
+        $requestData = ['entityItem' => $item->__toArray()];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $itemId,
+            $item[\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest::ID],
+            'Identifier replacing failed.'
+        );
+    }
+
+    /**
+     * Test if the framework works if camelCase path parameters are provided instead of valid snake case ones.
+     * Webapi Framework currently accepts both cases due to shortcoming in Serialization (MAGETWO-29833).
+     * Unless it is fixed this use case is valid.
+     */
+    public function testAddCaseMismatch()
+    {
+        $itemId = 1;
+        $incorrectItemId = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+        $requestData = ['entityItem' => ['entityId' => $incorrectItemId, 'name' => 'test']];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $itemId,
+            $item[\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest::ID],
+            'Identifier overriding failed.'
+        );
+    }
+
+    public function testOverrideWithScalarValues()
+    {
+        $firstItemId = 1;
+        $secondItemId = 11;
+        $incorrectItemId = 2;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => "/{$this->_version}/TestModule5/OverrideService/" . $firstItemId
+                    . '/nestedResource/' . $secondItemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+        ];
+
+        $requestData = ['entity_id' => $incorrectItemId, 'name' => 'test', 'orders' => true];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals(
+            $secondItemId,
+            $item[\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest::ID],
+            'Identifier overriding failed.'
+        );
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..18d169911f9fd95a5112de353d85d9fcb5565073
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RestErrorHandlingTest.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Test Web API error codes.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Routing;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Webapi\Exception as WebapiException;
+
+class RestErrorHandlingTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /**
+     * @var string
+     */
+    protected $mode;
+
+    protected function setUp()
+    {
+        $this->_markTestAsRestOnly();
+        $this->mode = Bootstrap::getObjectManager()->get('Magento\Framework\App\State')->getMode();
+        parent::setUp();
+    }
+
+    public function testSuccess()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/errortest/success',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+
+        $item = $this->_webApiCall($serviceInfo);
+
+        // TODO: check Http Status = 200, cannot do yet due to missing header info returned
+
+        $this->assertEquals('a good id', $item['value'], 'Success case is correct');
+    }
+
+    public function testNotFound()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/errortest/notfound',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+
+        // \Magento\Framework\Api\ResourceNotFoundException
+        $this->_errorTest(
+            $serviceInfo,
+            ['resource_id' => 'resourceY'],
+            WebapiException::HTTP_NOT_FOUND,
+            'Resource with ID "%resource_id" not found.'
+        );
+    }
+
+    public function testUnauthorized()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/errortest/unauthorized',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+
+        // \Magento\Framework\Api\AuthorizationException
+        $this->_errorTest(
+            $serviceInfo,
+            [],
+            WebapiException::HTTP_UNAUTHORIZED,
+            'Consumer is not authorized to access %resources',
+            ['resources' => 'resourceN']
+        );
+    }
+
+    public function testOtherException()
+    {
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => '/V1/errortest/otherexception',
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+        ];
+
+        /* TODO : Fix as part MAGETWO-31330
+        $expectedMessage = $this->mode == \Magento\Framework\App\State::MODE_DEVELOPER
+            ? 'Non service exception'
+            : 'Internal Error. Details are available in Magento log file. Report ID: webapi-XXX';
+        */
+        $expectedMessage = 'Internal Error. Details are available in Magento log file. Report ID: webapi-XXX';
+        $this->_errorTest(
+            $serviceInfo,
+            [],
+            WebapiException::HTTP_INTERNAL_ERROR,
+            $expectedMessage,
+            null,
+            'Magento\TestModule3\Service\V1\Error->otherException()' // Check if trace contains proper error source
+        );
+    }
+
+    /**
+     * Perform a negative REST api call test case and compare the results with expected values.
+     *
+     * @param string $serviceInfo - REST Service information (i.e. resource path and HTTP method)
+     * @param array $data - Data for the cal
+     * @param int $httpStatus - Expected HTTP status
+     * @param string|array $errorMessage - \Exception error message
+     * @param array $parameters - Optional parameters array, or null if no parameters
+     * @param string $traceString - Optional trace string to verify
+     */
+    protected function _errorTest(
+        $serviceInfo,
+        $data,
+        $httpStatus,
+        $errorMessage,
+        $parameters = [],
+        $traceString = null
+    ) {
+        try {
+            $this->_webApiCall($serviceInfo, $data);
+        } catch (\Exception $e) {
+            $this->assertEquals($httpStatus, $e->getCode(), 'Checking HTTP status code');
+
+            $body = json_decode($e->getMessage(), true);
+
+            $errorMessages = is_array($errorMessage) ? $errorMessage : [$errorMessage];
+            $actualMessage = $body['message'];
+            $matches = [];
+            //Report ID was created dynamically, so we need to replace it with some static value in order to test
+            if (preg_match('/.*Report\sID\:\s([a-zA-Z0-9\-]*)/', $actualMessage, $matches)) {
+                $actualMessage = str_replace($matches[1], 'webapi-XXX', $actualMessage);
+            }
+            //make sure that the match for a report with an id is found if Internal error was reported
+            //Refer : \Magento\Webapi\Controller\ErrorProcessor::INTERNAL_SERVER_ERROR_MSG
+            if (count($matches) > 1) {
+                $this->assertTrue(!empty($matches[1]), 'Report id missing for internal error.');
+            }
+            $this->assertContains(
+                $actualMessage,
+                $errorMessages,
+                "Message is invalid. Actual: '{$actualMessage}'. Expected one of: {'" . implode(
+                    "', '",
+                    $errorMessages
+                ) . "'}"
+            );
+
+            if ($parameters) {
+                $this->assertEquals($parameters, $body['parameters'], 'Checking body parameters');
+            }
+
+            if ($this->mode == \Magento\Framework\App\State::MODE_DEVELOPER && $traceString) {
+                // TODO : Fix as part MAGETWO-31330
+                //$this->assertContains($traceString, $body['trace'], 'Trace information is incorrect.');
+            }
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV1Test.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV1Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d0e97d268f3473b8464dc1a6925e8d99bc773215
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV1Test.php
@@ -0,0 +1,267 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+/**
+ * Class to test routing based on Service Versioning(for V1 version of a service)
+ */
+namespace Magento\Webapi\Routing;
+
+use Magento\Framework\Api\AttributeValue;
+use Magento\TestFramework\Authentication\OauthHelper;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestModule1\Service\V1\Entity\ItemBuilder;
+use Magento\Webapi\Model\Rest\Config as RestConfig;
+
+class ServiceVersionV1Test extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+    /**
+     * @var string
+     */
+    protected $_soapService = 'testModule1AllSoapAndRest';
+
+    /** @var \Magento\Framework\Api\AttributeDataBuilder */
+    protected $valueBuilder;
+
+    /** @var ItemBuilder */
+    protected $itemBuilder;
+
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_soapService = 'testModule1AllSoapAndRestV1';
+        $this->_restResourcePath = "/{$this->_version}/testmodule1/";
+
+        $this->valueBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\Framework\Api\AttributeDataBuilder'
+        );
+
+        $this->itemBuilder = Bootstrap::getObjectManager()->create(
+            'Magento\TestModule1\Service\V1\Entity\ItemBuilder'
+        );
+    }
+
+    /**
+     *  Test get item
+     */
+    public function testItem()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Item'],
+        ];
+        $requestData = ['itemId' => $itemId];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals('testProduct1', $item['name'], 'Item was retrieved unsuccessfully');
+    }
+
+    /**
+     *  Test get item with any type
+     */
+    public function testItemAnyType()
+    {
+        $this->_markTestAsRestOnly('Test will fail for SOAP because attribute values get converted to strings.');
+        $customerAttributes = [
+            ItemBuilder::CUSTOM_ATTRIBUTE_1 => [
+                AttributeValue::ATTRIBUTE_CODE => ItemBuilder::CUSTOM_ATTRIBUTE_1,
+                AttributeValue::VALUE => '12345',
+            ],
+            ItemBuilder::CUSTOM_ATTRIBUTE_2 => [
+                AttributeValue::ATTRIBUTE_CODE => ItemBuilder::CUSTOM_ATTRIBUTE_2,
+                AttributeValue::VALUE => 12345,
+            ],
+            ItemBuilder::CUSTOM_ATTRIBUTE_3 => [
+                AttributeValue::ATTRIBUTE_CODE => ItemBuilder::CUSTOM_ATTRIBUTE_3,
+                AttributeValue::VALUE => true,
+            ],
+        ];
+
+        $attributeValue1 = $this->valueBuilder
+            ->setAttributeCode(ItemBuilder::CUSTOM_ATTRIBUTE_1)
+            ->setValue('12345')
+            ->create();
+        $attributeValue2 = $this->valueBuilder
+            ->setAttributeCode(ItemBuilder::CUSTOM_ATTRIBUTE_2)
+            ->setValue(12345)
+            ->create();
+        $attributeValue3 = $this->valueBuilder
+            ->setAttributeCode(ItemBuilder::CUSTOM_ATTRIBUTE_3)
+            ->setValue(true)
+            ->create();
+
+        $item = $this->itemBuilder
+            ->setItemId(1)
+            ->setName('testProductAnyType')
+            ->setCustomAttributes([$attributeValue1, $attributeValue2, $attributeValue3])
+            ->create();
+
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'itemAnyType',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'ItemAnyType'],
+        ];
+        $requestData = $item->__toArray();
+        $item = $this->_webApiCall($serviceInfo, ['entityItem' => $requestData]);
+
+        $this->assertSame(
+            $attributeValue1->getValue(),
+            $item['custom_attributes'][0]['value'],
+            'Serialized attribute value type does\'t match pre-defined type.'
+        ); // string '12345' is expected
+
+        $this->assertSame(
+            $attributeValue2->getValue(),
+            $item['custom_attributes'][1]['value'],
+            'Serialized attribute value type does\'t match pre-defined type.'
+        ); // integer 12345 is expected
+
+        $this->assertSame(
+            $attributeValue3->getValue(),
+            $item['custom_attributes'][2]['value'],
+            'Serialized attribute value type does\'t match pre-defined type.'
+        ); // boolean true is expected
+    }
+
+    /**
+     * Test fetching all items
+     */
+    public function testItems()
+    {
+        $itemArr = [['item_id' => 1, 'name' => 'testProduct1'], ['item_id' => 2, 'name' => 'testProduct2']];
+        $serviceInfo = [
+            'rest' => ['resourcePath' => $this->_restResourcePath, 'httpMethod' => RestConfig::HTTP_METHOD_GET],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Items'],
+        ];
+        $item = $this->_webApiCall($serviceInfo);
+        $this->assertEquals($itemArr, $item, 'Items were not retrieved');
+    }
+
+    /**
+     *  Test create item
+     */
+    public function testCreate()
+    {
+        $createdItemName = 'createdItemName';
+        $serviceInfo = [
+            'rest' => ['resourcePath' => $this->_restResourcePath, 'httpMethod' => RestConfig::HTTP_METHOD_POST],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Create'],
+        ];
+        $requestData = ['name' => $createdItemName];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($createdItemName, $item['name'], 'Item creation failed');
+    }
+
+    /**
+     *  Test create item with missing proper resources
+     */
+    public function testCreateWithoutResources()
+    {
+        $createdItemName = 'createdItemName';
+        $serviceInfo = [
+            'rest' => ['resourcePath' => $this->_restResourcePath, 'httpMethod' => RestConfig::HTTP_METHOD_POST],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Create'],
+        ];
+        $requestData = ['name' => $createdItemName];
+
+        // getting new credentials that do not match the api resources
+        OauthHelper::clearApiAccessCredentials();
+        OauthHelper::getApiAccessCredentials([]);
+        try {
+            $this->assertUnauthorizedException($serviceInfo, $requestData);
+        } catch (\Exception $e) {
+            OauthHelper::clearApiAccessCredentials();
+            throw $e;
+        }
+        // to allow good credentials to be restored (this is statically stored on OauthHelper)
+        OauthHelper::clearApiAccessCredentials();
+    }
+
+    /**
+     *  Test update item
+     */
+    public function testUpdate()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_PUT,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Update'],
+        ];
+        $requestData = ['entityItem' => ['itemId' => $itemId, 'name' => 'testName']];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals('Updated' . $requestData['entityItem']['name'], $item['name'], 'Item update failed');
+    }
+
+    /**
+     *  Negative Test: Invoking non-existent delete api which is only available in V2
+     */
+    public function testDelete()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => RestConfig::HTTP_METHOD_DELETE,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Delete'],
+        ];
+        $requestData = ['itemId' => $itemId, 'name' => 'testName'];
+        $this->_assertNoRouteOrOperationException($serviceInfo, $requestData);
+    }
+
+    public function testOverwritten()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'overwritten',
+                'httpMethod' => RestConfig::HTTP_METHOD_GET,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, []);
+        $this->assertEquals(['item_id' => -55, 'name' => 'testProduct1'], $item);
+    }
+
+    public function testDefaulted()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'testOptionalParam',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, []);
+        $this->assertEquals(['item_id' => 3, 'name' => 'Default Name'], $item);
+    }
+
+    public function testDefaultedWithValue()
+    {
+        $this->_markTestAsRestOnly();
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . 'testOptionalParam',
+                'httpMethod' => RestConfig::HTTP_METHOD_POST,
+            ],
+        ];
+        $item = $this->_webApiCall($serviceInfo, ['name' => 'Ms. LaGrange']);
+        $this->assertEquals(['item_id' => 3, 'name' => 'Ms. LaGrange'], $item);
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV2Test.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV2Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..44707fb779da6960c671bb81e0d9fab78fee2a85
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/ServiceVersionV2Test.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Webapi\Routing;
+
+class ServiceVersionV2Test extends \Magento\Webapi\Routing\BaseService
+{
+    protected function setUp()
+    {
+        $this->_version = 'V2';
+        $this->_soapService = 'testModule1AllSoapAndRestV2';
+        $this->_restResourcePath = "/{$this->_version}/testmodule1/";
+    }
+
+    /**
+     *  Test to assert overriding of the existing 'Item' api in V2 version of the same service
+     */
+    public function testItem()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Item'],
+        ];
+        $requestData = ['id' => $itemId];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        // Asserting for additional attribute returned by the V2 api
+        $this->assertEquals(1, $item['price'], 'Item was retrieved unsuccessfully from V2');
+    }
+
+    /**
+     * Test fetching all items
+     */
+    public function testItems()
+    {
+        $itemArr = [
+            ['id' => 1, 'name' => 'testProduct1', 'price' => '1'],
+            ['id' => 2, 'name' => 'testProduct2', 'price' => '2'],
+        ];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Items'],
+        ];
+        $item = $this->_webApiCall($serviceInfo);
+        $this->assertEquals($itemArr, $item, 'Items were not retrieved');
+    }
+
+    /**
+     * Test fetching items when filters are applied
+     *
+     * @param string[] $filters
+     * @param array $expectedResult
+     * @dataProvider itemsWithFiltersDataProvider
+     */
+    public function testItemsWithFilters($filters, $expectedResult)
+    {
+        $restFilter = '';
+        foreach ($filters as $filterItemKey => $filterMetadata) {
+            foreach ($filterMetadata as $filterMetaKey => $filterMetaValue) {
+                $paramsDelimiter = empty($restFilter) ? '?' : '&';
+                $restFilter .= "{$paramsDelimiter}filters[{$filterItemKey}][{$filterMetaKey}]={$filterMetaValue}";
+            }
+        }
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $restFilter,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => [
+                'service' => $this->_soapService,
+                'operation' => $this->_soapService . 'Items',
+            ],
+        ];
+        $requestData = [];
+        if (!empty($filters)) {
+            $requestData['filters'] = $filters;
+        }
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($expectedResult, $item, 'Filtration does not seem to work correctly.');
+    }
+
+    public function itemsWithFiltersDataProvider()
+    {
+        $firstItem = ['id' => 1, 'name' => 'testProduct1', 'price' => 1];
+        $secondItem = ['id' => 2, 'name' => 'testProduct2', 'price' => 2];
+        return [
+            'Both items filter' => [
+                [
+                    ['field' => 'id', 'conditionType' => 'eq','value' => 1],
+                    ['field' => 'id', 'conditionType' => 'eq','value' => 2],
+                ],
+                [$firstItem, $secondItem],
+            ],
+            'First item filter' => [[['field' => 'id', 'conditionType' => 'eq','value' => 1]], [$firstItem]],
+            'Second item filter' => [[['field' => 'id', 'conditionType' => 'eq','value' => 2]], [$secondItem]],
+            'Empty filter' => [[], [$firstItem, $secondItem]],
+        ];
+    }
+
+    /**
+     *  Test update item
+     */
+    public function testUpdate()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_PUT,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Update'],
+        ];
+        $requestData = ['entityItem' => ['id' => $itemId, 'name' => 'testName', 'price' => '4']];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals('Updated' . $requestData['entityItem']['name'], $item['name'], 'Item update failed');
+    }
+
+    /**
+     *  Test to assert presence of new 'delete' api added in V2 version of the same service
+     */
+    public function testDelete()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_DELETE,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Delete'],
+        ];
+        $requestData = ['id' => $itemId, 'name' => 'testName'];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($itemId, $item['id'], "Item delete failed");
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d84f5fe8198b26cf1913e59d06e678ed0d93898e
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi\Routing;
+
+use Magento\Framework\Exception\AuthorizationException;
+
+/**
+ * SOAP error handling test.
+ */
+class SoapErrorHandlingTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    protected function setUp()
+    {
+        $this->_markTestAsSoapOnly();
+        parent::setUp();
+    }
+
+    public function testWebapiException()
+    {
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'testModule3ErrorV1',
+                'operation' => 'testModule3ErrorV1WebapiException',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo);
+            $this->fail("SoapFault was not raised as expected.");
+        } catch (\SoapFault $e) {
+            $this->checkSoapFault(
+                $e,
+                'Service not found',
+                'env:Sender'
+            );
+        }
+    }
+
+    public function testUnknownException()
+    {
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'testModule3ErrorV1',
+                'operation' => 'testModule3ErrorV1OtherException',
+            ],
+        ];
+        try {
+            $this->_webApiCall($serviceInfo);
+            $this->fail("SoapFault was not raised as expected.");
+        } catch (\SoapFault $e) {
+            /** In developer mode message is masked, so checks should be different in two modes */
+            if (strpos($e->getMessage(), 'Internal Error') === false) {
+                $this->checkSoapFault(
+                    $e,
+                    'Non service exception',
+                    'env:Receiver',
+                    null,
+                    null,
+                    'Magento\TestModule3\Service\V1\Error->otherException()'
+                );
+            } else {
+                $this->checkSoapFault(
+                    $e,
+                    'Internal Error. Details are available in Magento log file. Report ID:',
+                    'env:Receiver'
+                );
+            }
+        }
+    }
+
+    public function testEmptyInputException()
+    {
+        $parameters = [];
+        $this->_testWrappedError($parameters);
+    }
+
+    public function testSingleWrappedErrorException()
+    {
+        $parameters = [
+            ['fieldName' => 'key1', 'value' => 'value1'],
+        ];
+        $this->_testWrappedError($parameters);
+    }
+
+    public function testMultipleWrappedErrorException()
+    {
+        $parameters = [
+            ['fieldName' => 'key1', 'value' => 'value1'],
+            ['fieldName' => 'key2', 'value' => 'value2'],
+        ];
+        $this->_testWrappedError($parameters);
+    }
+
+    public function testUnauthorized()
+    {
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'testModule3ErrorV1',
+                'operation' => 'testModule3ErrorV1AuthorizationException',
+                'token' => 'invalidToken',
+            ],
+        ];
+
+        $expectedException = new AuthorizationException(
+            AuthorizationException::NOT_AUTHORIZED,
+            ['resources' => 'Magento_TestModule3::resource1, Magento_TestModule3::resource2']
+        );
+
+        try {
+            $this->_webApiCall($serviceInfo);
+            $this->fail("SoapFault was not raised as expected.");
+        } catch (\SoapFault $e) {
+            $this->checkSoapFault(
+                $e,
+                $expectedException->getRawMessage(),
+                'env:Sender',
+                $expectedException->getParameters() // expected error parameters
+            );
+        }
+    }
+
+    protected function _testWrappedError($parameters)
+    {
+        $serviceInfo = [
+            'soap' => [
+                'service' => 'testModule3ErrorV1',
+                'operation' => 'testModule3ErrorV1InputException',
+            ],
+        ];
+
+        $expectedException = new \Magento\Framework\Exception\InputException();
+        foreach ($parameters as $error) {
+            $expectedException->addError(\Magento\Framework\Exception\InputException::INVALID_FIELD_VALUE, $error);
+        }
+
+        $arguments = [
+            'wrappedErrorParameters' => $parameters,
+        ];
+
+        $expectedErrors = [];
+        foreach ($expectedException->getErrors() as $key => $error) {
+            $expectedErrors[$key] = [
+                'message' => $error->getRawMessage(),
+                'params' => $error->getParameters(),
+            ];
+        }
+
+        try {
+            $this->_webApiCall($serviceInfo, $arguments);
+            $this->fail("SoapFault was not raised as expected.");
+        } catch (\SoapFault $e) {
+            $this->checkSoapFault(
+                $e,
+                $expectedException->getRawMessage(),
+                'env:Sender',
+                $expectedException->getParameters(), // expected error parameters
+                $expectedErrors                      // expected wrapped errors
+            );
+        }
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SubsetTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SubsetTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9b3aac72be7cab13a84317d72235c88c4b2c625
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SubsetTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+/**
+ * Class to test routing based on a Service that exposes subset of operations
+ */
+namespace Magento\Webapi\Routing;
+
+class SubsetTest extends \Magento\Webapi\Routing\BaseService
+{
+    /**
+     * @var string
+     */
+    protected $_version;
+
+    /**
+     * @var string
+     */
+    protected $_restResourcePath;
+
+    /**
+     * @var string
+     */
+    protected $_soapService;
+
+    /**
+     * @Override
+     */
+    protected function setUp()
+    {
+        $this->_version = 'V1';
+        $this->_restResourcePath = "/{$this->_version}/testModule2SubsetRest/";
+        $this->_soapService = 'testModule2SubsetRestV1';
+    }
+
+    /**
+     * @Override
+     * Test get item
+     */
+    public function testItem()
+    {
+        $itemId = 1;
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath . $itemId,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Item'],
+        ];
+        $requestData = ['id' => $itemId];
+        $item = $this->_webApiCall($serviceInfo, $requestData);
+        $this->assertEquals($itemId, $item['id'], 'Item was retrieved unsuccessfully');
+    }
+
+    /**
+     * @Override
+     * Test fetching all items
+     */
+    public function testItems()
+    {
+        $itemArr = [['id' => 1, 'name' => 'testItem1'], ['id' => 2, 'name' => 'testItem2']];
+        $serviceInfo = [
+            'rest' => [
+                'resourcePath' => $this->_restResourcePath,
+                'httpMethod' => \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_GET,
+            ],
+            'soap' => ['service' => $this->_soapService, 'operation' => $this->_soapService . 'Items'],
+        ];
+
+        $item = $this->_webApiCall($serviceInfo);
+        $this->assertEquals($itemArr, $item, 'Items were not retrieved');
+    }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f27b6179ec55ddb06d290b61c6e6ded4dc1c943
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php
@@ -0,0 +1,735 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Webapi;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * Test WSDL generation mechanisms.
+ */
+class WsdlGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\WebapiAbstract
+{
+    /** @var string */
+    protected $_baseUrl = TESTS_BASE_URL;
+
+    /** @var string */
+    protected $_storeCode;
+
+    /** @var string */
+    protected $_soapUrl;
+
+    protected function setUp()
+    {
+        $this->_markTestAsSoapOnly("WSDL generation tests are intended to be executed for SOAP adapter only.");
+        $this->_storeCode = Bootstrap::getObjectManager()->get('Magento\Store\Model\StoreManagerInterface')
+            ->getStore()->getCode();
+        $this->_soapUrl = "{$this->_baseUrl}/soap/{$this->_storeCode}?services%3DtestModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2";
+        parent::setUp();
+    }
+
+    public function testMultiServiceWsdl()
+    {
+        if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+            $this->markTestIncomplete('MAGETWO-31016: incompatible with ZF 1.12.9');
+        }
+        $wsdlUrl = $this->_getBaseWsdlUrl() . 'testModule5AllSoapAndRestV1,testModule5AllSoapAndRestV2';
+        $wsdlContent = $this->_convertXmlToString($this->_getWsdlContent($wsdlUrl));
+
+        $this->_checkTypesDeclaration($wsdlContent);
+        $this->_checkPortTypeDeclaration($wsdlContent);
+        $this->_checkBindingDeclaration($wsdlContent);
+        $this->_checkServiceDeclaration($wsdlContent);
+        $this->_checkMessagesDeclaration($wsdlContent);
+        $this->_checkFaultsDeclaration($wsdlContent);
+    }
+
+    public function testInvalidWsdlUrlNoServices()
+    {
+        $responseContent = $this->_getWsdlContent($this->_getBaseWsdlUrl());
+        $this->assertContains("Requested services are missing.", $responseContent);
+    }
+
+    public function testInvalidWsdlUrlInvalidParameter()
+    {
+        $wsdlUrl = $this->_getBaseWsdlUrl() . '&invalid';
+        $responseContent = $this->_getWsdlContent($wsdlUrl);
+        $this->assertContains("Not allowed parameters", $responseContent);
+    }
+
+    /**
+     * Remove unnecessary spaces and line breaks from xml string.
+     *
+     * @param string $xml
+     * @return string
+     */
+    protected function _convertXmlToString($xml)
+    {
+        return str_replace(['    ', "\n", "\r", "&#13;", "&#10;"], '', $xml);
+    }
+
+    /**
+     * Retrieve WSDL content.
+     *
+     * @param string $wsdlUrl
+     * @return string|boolean
+     */
+    protected function _getWsdlContent($wsdlUrl)
+    {
+        $connection = curl_init($wsdlUrl);
+        curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
+        $responseContent = curl_exec($connection);
+        $responseDom = new \DOMDocument();
+        $this->assertTrue(
+            $responseDom->loadXML($responseContent),
+            "Valid XML is always expected as a response for WSDL request."
+        );
+        return $responseContent;
+    }
+
+    /**
+     * Generate base WSDL URL (without any services specified)
+     *
+     * @return string
+     */
+    protected function _getBaseWsdlUrl()
+    {
+        /** @var \Magento\TestFramework\TestCase\Webapi\Adapter\Soap $soapAdapter */
+        $soapAdapter = $this->_getWebApiAdapter(self::ADAPTER_SOAP);
+        $wsdlUrl = $soapAdapter->generateWsdlUrl([]);
+        return $wsdlUrl;
+    }
+
+    /**
+     * Ensure that types section has correct structure.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkTypesDeclaration($wsdlContent)
+    {
+        // @codingStandardsIgnoreStart
+        $typesSectionDeclaration = <<< TYPES_SECTION_DECLARATION
+<types>
+    <xsd:schema targetNamespace="{$this->_soapUrl}">
+TYPES_SECTION_DECLARATION;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($typesSectionDeclaration),
+            $wsdlContent,
+            'Types section declaration is invalid'
+        );
+        $this->_checkElementsDeclaration($wsdlContent);
+        $this->_checkComplexTypesDeclaration($wsdlContent);
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkElementsDeclaration($wsdlContent)
+    {
+        $requestElement = <<< REQUEST_ELEMENT
+<xsd:element name="testModule5AllSoapAndRestV1ItemRequest" type="tns:TestModule5AllSoapAndRestV1ItemRequest"/>
+REQUEST_ELEMENT;
+        $this->assertContains(
+            $this->_convertXmlToString($requestElement),
+            $wsdlContent,
+            'Request element declaration in types section is invalid'
+        );
+        $responseElement = <<< RESPONSE_ELEMENT
+<xsd:element name="testModule5AllSoapAndRestV1ItemResponse" type="tns:TestModule5AllSoapAndRestV1ItemResponse"/>
+RESPONSE_ELEMENT;
+        $this->assertContains(
+            $this->_convertXmlToString($responseElement),
+            $wsdlContent,
+            'Response element declaration in types section is invalid'
+        );
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkComplexTypesDeclaration($wsdlContent)
+    {
+        // @codingStandardsIgnoreStart
+        $requestType = <<< REQUEST_TYPE
+<xsd:complexType name="TestModule5AllSoapAndRestV1ItemRequest">
+    <xsd:annotation>
+        <xsd:documentation>Retrieve an item.</xsd:documentation>
+        <xsd:appinfo xmlns:inf="{$this->_soapUrl}"/>
+    </xsd:annotation>
+    <xsd:sequence>
+        <xsd:element name="entityId" minOccurs="1" maxOccurs="1" type="xsd:int">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:min/>
+                    <inf:max/>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:requiredInput>Yes</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+REQUEST_TYPE;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($requestType),
+            $wsdlContent,
+            'Request type declaration in types section is invalid'
+        );
+        // @codingStandardsIgnoreStart
+        $responseType = <<< RESPONSE_TYPE
+<xsd:complexType name="TestModule5AllSoapAndRestV1ItemResponse">
+    <xsd:annotation>
+        <xsd:documentation>
+            Response container for the testModule5AllSoapAndRestV1Item call.
+        </xsd:documentation>
+        <xsd:appinfo xmlns:inf="{$this->_soapUrl}"/>
+    </xsd:annotation>
+    <xsd:sequence>
+        <xsd:element name="result" minOccurs="1" maxOccurs="1" type="tns:TestModule5V1EntityAllSoapAndRest">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:returned>Always</inf:returned>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+RESPONSE_TYPE;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($responseType),
+            $wsdlContent,
+            'Response type declaration in types section is invalid'
+        );
+        $this->_checkReferencedTypeDeclaration($wsdlContent);
+    }
+
+    /**
+     * Ensure that complex type generated from Data Object is correct.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkReferencedTypeDeclaration($wsdlContent)
+    {
+        // @codingStandardsIgnoreStart
+        $referencedType = <<< RESPONSE_TYPE
+<xsd:complexType name="TestModule5V1EntityAllSoapAndRest">
+    <xsd:annotation>
+        <xsd:documentation>Some Data Object short description. Data Object long multi line description.</xsd:documentation>
+        <xsd:appinfo xmlns:inf="{$this->_soapUrl}"/>
+    </xsd:annotation>
+    <xsd:sequence>
+        <xsd:element name="entityId" minOccurs="1" maxOccurs="1" type="xsd:int">
+            <xsd:annotation>
+                <xsd:documentation>Item ID</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:min/>
+                    <inf:max/>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:returned>Always</inf:returned>
+                    </inf:callInfo>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:requiredInput>Yes</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="name" minOccurs="0" maxOccurs="1" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation>Item name</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:maxLength/>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:returned>Conditionally</inf:returned>
+                    </inf:callInfo>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:requiredInput>No</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="enabled" minOccurs="1" maxOccurs="1" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:default>false</inf:default>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:returned>Conditionally</inf:returned>
+                    </inf:callInfo>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:requiredInput>No</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="orders" minOccurs="1" maxOccurs="1" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:default>false</inf:default>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:returned>Conditionally</inf:returned>
+                    </inf:callInfo>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:requiredInput>No</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="customAttributes" type="tns:ArrayOfFrameworkAttributeInterface" minOccurs="0">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:natureOfType>array</inf:natureOfType>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Item</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:returned>Conditionally</inf:returned>
+                    </inf:callInfo>
+                    <inf:callInfo>
+                        <inf:callName>testModule5AllSoapAndRestV1Create</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1Update</inf:callName>
+                        <inf:callName>testModule5AllSoapAndRestV1NestedUpdate</inf:callName>
+                        <inf:requiredInput>No</inf:requiredInput>
+                    </inf:callInfo>
+                </xsd:appinfo>
+            </xsd:annotation>
+    </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+RESPONSE_TYPE;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($referencedType),
+            $wsdlContent,
+            'Declaration of complex type generated from Data Object, which is referenced in response, is invalid'
+        );
+    }
+
+    /**
+     * Ensure that port type sections have correct structure.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkPortTypeDeclaration($wsdlContent)
+    {
+        $firstPortType = <<< FIRST_PORT_TYPE
+<portType name="testModule5AllSoapAndRestV1PortType">
+FIRST_PORT_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($firstPortType),
+            $wsdlContent,
+            'Port type declaration is missing or invalid'
+        );
+        $secondPortType = <<< SECOND_PORT_TYPE
+<portType name="testModule5AllSoapAndRestV2PortType">
+SECOND_PORT_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($secondPortType),
+            $wsdlContent,
+            'Port type declaration is missing or invalid'
+        );
+        $operationDeclaration = <<< OPERATION_DECLARATION
+<operation name="testModule5AllSoapAndRestV2Item">
+    <input message="tns:testModule5AllSoapAndRestV2ItemRequest"/>
+    <output message="tns:testModule5AllSoapAndRestV2ItemResponse"/>
+    <fault name="GenericFault" message="tns:GenericFault"/>
+</operation>
+<operation name="testModule5AllSoapAndRestV2Items">
+    <input message="tns:testModule5AllSoapAndRestV2ItemsRequest"/>
+    <output message="tns:testModule5AllSoapAndRestV2ItemsResponse"/>
+    <fault name="GenericFault" message="tns:GenericFault"/>
+</operation>
+OPERATION_DECLARATION;
+        $this->assertContains(
+            $this->_convertXmlToString($operationDeclaration),
+            $wsdlContent,
+            'Operation in port type is invalid'
+        );
+    }
+
+    /**
+     * Ensure that binding sections have correct structure.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkBindingDeclaration($wsdlContent)
+    {
+        $firstBinding = <<< FIRST_BINDING
+<binding name="testModule5AllSoapAndRestV1Binding" type="tns:testModule5AllSoapAndRestV1PortType">
+    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+FIRST_BINDING;
+        $this->assertContains(
+            $this->_convertXmlToString($firstBinding),
+            $wsdlContent,
+            'Binding declaration is missing or invalid'
+        );
+        $secondBinding = <<< SECOND_BINDING
+<binding name="testModule5AllSoapAndRestV2Binding" type="tns:testModule5AllSoapAndRestV2PortType">
+    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+SECOND_BINDING;
+        $this->assertContains(
+            $this->_convertXmlToString($secondBinding),
+            $wsdlContent,
+            'Binding declaration is missing or invalid'
+        );
+        $operationDeclaration = <<< OPERATION_DECLARATION
+<operation name="testModule5AllSoapAndRestV1Item">
+    <soap:operation soapAction="testModule5AllSoapAndRestV1Item"/>
+    <input>
+        <soap12:body use="literal"/>
+    </input>
+    <output>
+        <soap12:body use="literal"/>
+    </output>
+    <fault name="GenericFault">
+        <soap12:fault use="literal" name="GenericFault"/>
+    </fault>
+</operation>
+<operation name="testModule5AllSoapAndRestV1Items">
+    <soap:operation soapAction="testModule5AllSoapAndRestV1Items"/>
+    <input>
+        <soap12:body use="literal"/>
+    </input>
+    <output>
+        <soap12:body use="literal"/>
+    </output>
+    <fault name="GenericFault">
+        <soap12:fault use="literal" name="GenericFault"/>
+    </fault>
+</operation>
+OPERATION_DECLARATION;
+        $this->assertContains(
+            $this->_convertXmlToString($operationDeclaration),
+            $wsdlContent,
+            'Operation in binding is invalid'
+        );
+    }
+
+    /**
+     * Ensure that service sections have correct structure.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkServiceDeclaration($wsdlContent)
+    {
+        // @codingStandardsIgnoreStart
+        $firstServiceDeclaration = <<< FIRST_SERVICE_DECLARATION
+<service name="testModule5AllSoapAndRestV1Service">
+    <port name="testModule5AllSoapAndRestV1Port" binding="tns:testModule5AllSoapAndRestV1Binding">
+        <soap:address location="{$this->_baseUrl}/soap/{$this->_storeCode}?services=testModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2"/>
+    </port>
+</service>
+FIRST_SERVICE_DECLARATION;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($firstServiceDeclaration),
+            $wsdlContent,
+            'First service section is invalid'
+        );
+
+        // @codingStandardsIgnoreStart
+        $secondServiceDeclaration = <<< SECOND_SERVICE_DECLARATION
+<service name="testModule5AllSoapAndRestV2Service">
+    <port name="testModule5AllSoapAndRestV2Port" binding="tns:testModule5AllSoapAndRestV2Binding">
+        <soap:address location="{$this->_baseUrl}/soap/{$this->_storeCode}?services=testModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2"/>
+    </port>
+</service>
+SECOND_SERVICE_DECLARATION;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($secondServiceDeclaration),
+            $wsdlContent,
+            'Second service section is invalid'
+        );
+    }
+
+    /**
+     * Ensure that messages sections have correct structure.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkMessagesDeclaration($wsdlContent)
+    {
+        $itemMessagesDeclaration = <<< MESSAGES_DECLARATION
+<message name="testModule5AllSoapAndRestV2ItemRequest">
+    <part name="messageParameters" element="tns:testModule5AllSoapAndRestV2ItemRequest"/>
+</message>
+<message name="testModule5AllSoapAndRestV2ItemResponse">
+    <part name="messageParameters" element="tns:testModule5AllSoapAndRestV2ItemResponse"/>
+</message>
+MESSAGES_DECLARATION;
+        $this->assertContains(
+            $this->_convertXmlToString($itemMessagesDeclaration),
+            $wsdlContent,
+            'Messages section for "item" operation is invalid'
+        );
+        $itemsMessagesDeclaration = <<< MESSAGES_DECLARATION
+<message name="testModule5AllSoapAndRestV2ItemsRequest">
+    <part name="messageParameters" element="tns:testModule5AllSoapAndRestV2ItemsRequest"/>
+</message>
+<message name="testModule5AllSoapAndRestV2ItemsResponse">
+    <part name="messageParameters" element="tns:testModule5AllSoapAndRestV2ItemsResponse"/>
+</message>
+MESSAGES_DECLARATION;
+        $this->assertContains(
+            $this->_convertXmlToString($itemsMessagesDeclaration),
+            $wsdlContent,
+            'Messages section for "items" operation is invalid'
+        );
+    }
+
+    /**
+     * Ensure that SOAP faults are declared properly.
+     *
+     * @param string $wsdlContent
+     */
+    protected function _checkFaultsDeclaration($wsdlContent)
+    {
+        $this->_checkFaultsPortTypeSection($wsdlContent);
+        $this->_checkFaultsBindingSection($wsdlContent);
+        $this->_checkFaultsMessagesSection($wsdlContent);
+        $this->_checkFaultsComplexTypeSection($wsdlContent);
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkFaultsPortTypeSection($wsdlContent)
+    {
+        $faultsInPortType = <<< FAULT_IN_PORT_TYPE
+<fault name="GenericFault" message="tns:GenericFault"/>
+FAULT_IN_PORT_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($faultsInPortType),
+            $wsdlContent,
+            'SOAP Fault section in port type section is invalid'
+        );
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkFaultsBindingSection($wsdlContent)
+    {
+        $faultsInBinding = <<< FAULT_IN_BINDING
+<fault name="GenericFault">
+    <soap12:fault use="literal" name="GenericFault"/>
+</fault>
+FAULT_IN_BINDING;
+        $this->assertContains(
+            $this->_convertXmlToString($faultsInBinding),
+            $wsdlContent,
+            'SOAP Fault section in binding section is invalid'
+        );
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkFaultsMessagesSection($wsdlContent)
+    {
+        $genericFaultMessage = <<< GENERIC_FAULT_IN_MESSAGES
+<message name="GenericFault">
+    <part name="messageParameters" element="tns:GenericFault"/>
+</message>
+GENERIC_FAULT_IN_MESSAGES;
+        $this->assertContains(
+            $this->_convertXmlToString($genericFaultMessage),
+            $wsdlContent,
+            'Generic SOAP Fault declaration in messages section is invalid'
+        );
+    }
+
+    /**
+     * @param string $wsdlContent
+     */
+    protected function _checkFaultsComplexTypeSection($wsdlContent)
+    {
+        $this->assertContains(
+            $this->_convertXmlToString('<xsd:element name="GenericFault" type="tns:GenericFault"/>'),
+            $wsdlContent,
+            'Default SOAP Fault complex type element declaration is invalid'
+        );
+
+        // @codingStandardsIgnoreStart
+        $genericFaultType = <<< GENERIC_FAULT_COMPLEX_TYPE
+<xsd:complexType name="GenericFault">
+    <xsd:sequence>
+        <xsd:element name="Trace" minOccurs="0" maxOccurs="1" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation>Exception calls stack trace.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:maxLength/>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="Parameters" type="tns:ArrayOfGenericFaultParameter" minOccurs="0">
+            <xsd:annotation>
+                <xsd:documentation>Additional exception parameters.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:natureOfType>array</inf:natureOfType>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="WrappedErrors" type="tns:ArrayOfWrappedError" minOccurs="0">
+            <xsd:annotation>
+                <xsd:documentation>Additional wrapped errors.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:natureOfType>array</inf:natureOfType>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+GENERIC_FAULT_COMPLEX_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($genericFaultType),
+            $wsdlContent,
+            'Default SOAP Fault complex types declaration is invalid'
+        );
+
+        $detailsParameterType = <<< PARAM_COMPLEX_TYPE
+<xsd:complexType name="GenericFaultParameter">
+    <xsd:sequence>
+        <xsd:element name="key" minOccurs="1" maxOccurs="1" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:maxLength/>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="value" minOccurs="1" maxOccurs="1" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}">
+                    <inf:maxLength/>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+PARAM_COMPLEX_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($detailsParameterType),
+            $wsdlContent,
+            'Details parameter complex types declaration is invalid.'
+        );
+
+        $detailsWrappedErrorType = <<< WRAPPED_ERROR_COMPLEX_TYPE
+<xsd:complexType name="WrappedError">
+    <xsd:sequence>
+        <xsd:element name="message" minOccurs="1" maxOccurs="1" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation></xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_baseUrl}/soap/{$this->_storeCode}?services%3DtestModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2">
+                    <inf:maxLength/>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+        <xsd:element name="parameters" type="tns:ArrayOfGenericFaultParameter" minOccurs="0">
+            <xsd:annotation>
+                <xsd:documentation>Message parameters.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_baseUrl}/soap/{$this->_storeCode}?services%3DtestModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2">
+                    <inf:natureOfType>array</inf:natureOfType>
+                </xsd:appinfo>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+WRAPPED_ERROR_COMPLEX_TYPE;
+        $this->assertContains(
+            $this->_convertXmlToString($detailsWrappedErrorType),
+            $wsdlContent,
+            'Details wrapped error complex types declaration is invalid.'
+        );
+
+        $detailsParametersType = <<< PARAMETERS_COMPLEX_TYPE
+<xsd:complexType name="ArrayOfGenericFaultParameter">
+    <xsd:annotation>
+        <xsd:documentation>An array of GenericFaultParameter items.</xsd:documentation>
+        <xsd:appinfo xmlns:inf="{$this->_soapUrl}"/>
+    </xsd:annotation>
+    <xsd:sequence>
+        <xsd:element name="item" minOccurs="0" maxOccurs="unbounded" type="tns:GenericFaultParameter">
+            <xsd:annotation>
+                <xsd:documentation>An item of ArrayOfGenericFaultParameter.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_soapUrl}"/>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+PARAMETERS_COMPLEX_TYPE;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($detailsParametersType),
+            $wsdlContent,
+            'Details parameters (array of parameters) complex types declaration is invalid.'
+        );
+
+        $detailsWrappedErrorsType = <<< WRAPPED_ERRORS_COMPLEX_TYPE
+<xsd:complexType name="ArrayOfWrappedError">
+    <xsd:annotation>
+        <xsd:documentation>An array of WrappedError items.</xsd:documentation>
+        <xsd:appinfo xmlns:inf="{$this->_baseUrl}/soap/{$this->_storeCode}?services%3DtestModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2"/>
+    </xsd:annotation>
+    <xsd:sequence>
+        <xsd:element name="item" minOccurs="0" maxOccurs="unbounded" type="tns:WrappedError">
+            <xsd:annotation>
+                <xsd:documentation>An item of ArrayOfWrappedError.</xsd:documentation>
+                <xsd:appinfo xmlns:inf="{$this->_baseUrl}/soap/{$this->_storeCode}?services%3DtestModule5AllSoapAndRestV1%2CtestModule5AllSoapAndRestV2"/>
+            </xsd:annotation>
+        </xsd:element>
+    </xsd:sequence>
+</xsd:complexType>
+WRAPPED_ERRORS_COMPLEX_TYPE;
+        // @codingStandardsIgnoreEnd
+        $this->assertContains(
+            $this->_convertXmlToString($detailsWrappedErrorsType),
+            $wsdlContent,
+            'Details wrapped errors (array of wrapped errors) complex types declaration is invalid.'
+        );
+    }
+}
diff --git a/dev/tests/functional/.gitignore b/dev/tests/functional/.gitignore
index f12c1a579105c852eae99d7f3f99befa173cb4a0..d3b32c5f1d405f9a8bb0a4b6ba742409c6f6050b 100755
--- a/dev/tests/functional/.gitignore
+++ b/dev/tests/functional/.gitignore
@@ -3,6 +3,9 @@
 /generated
 /var
 /config/*
-!/config/*.dist
+!/config/application.yml.dist
+!/config/handler.yml.dist
+!/config/isolation.yml.dist
+!/config/server.yml.dist
 phpunit.xml
 /lib/Mtf/Util/Generate/testcase.xml
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index ab4bd87728a6789a1b2ec6f575ccb1cf1ce8b45c..e2e3d4ad289ce347e9c3fade95d09f606d490ea5 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,6 +1,6 @@
 {
     "require": {
-        "magento/mtf": "1.0.0-rc10",
+        "magento/mtf": "1.0.0-rc11",
         "php": ">=5.4.0",
         "phpunit/phpunit": "4.1.0",
         "phpunit/phpunit-selenium": ">=1.2",
diff --git a/dev/tests/functional/lib/Mtf/App/State/AbstractState.php b/dev/tests/functional/lib/Mtf/App/State/AbstractState.php
index f83a0102f950401ce9618f91b5e9c20c52d3a8c7..dacaadb572424a58b489b9a550657796e073bf5c 100644
--- a/dev/tests/functional/lib/Mtf/App/State/AbstractState.php
+++ b/dev/tests/functional/lib/Mtf/App/State/AbstractState.php
@@ -38,7 +38,7 @@ abstract class AbstractState implements StateInterface
      */
     public function clearInstance()
     {
-        $dirList = \Mtf\ObjectManagerFactory::getObjectManager()->get('\Magento\Framework\Filesystem\DirectoryList');
+        $dirList = \Mtf\ObjectManagerFactory::getObjectManager()->get('Magento\Framework\Filesystem\DirectoryList');
         $deploymentConfig = new \Magento\Framework\App\DeploymentConfig(
             new \Magento\Framework\App\DeploymentConfig\Reader($dirList),
             []
diff --git a/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php b/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php
index 9ff3fa478573038c63a8a31642916c41a5be6fbc..dae63661d8efb2c7033ca187d45a8ff820a72e41 100644
--- a/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php
+++ b/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php
@@ -161,7 +161,10 @@ abstract class AbstractFactory
                 } else {
                     $dirIterator = new \RegexIterator(
                         new \RecursiveIteratorIterator(
-                            new \RecursiveDirectoryIterator($filePath, \FilesystemIterator::SKIP_DOTS)
+                            new \RecursiveDirectoryIterator(
+                                $filePath,
+                                \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS
+                            )
                         ),
                         '/.php$/i'
                     );
@@ -190,9 +193,10 @@ abstract class AbstractFactory
     {
         $filename = str_replace('\\', '/', $filename);
 
-        $classPath = str_replace(MTF_BP . '/' . $path . '/', '', $filename);
-        $classPath = str_replace('.php', '', $classPath);
-        $className = str_replace('/', '\\', $classPath);
+        $posTestsPath = strpos($filename, $path);
+        $posClassName = $posTestsPath + strlen($path);
+        $classPath = str_replace('.php', '', $filename);
+        $className = str_replace('/', '\\', substr($classPath, $posClassName));
 
         $reflectionClass = new \ReflectionClass($className);
         if ($reflectionClass->isAbstract()) {
diff --git a/dev/tests/functional/lib/Mtf/Util/Generate/Repository/TableCollection.php b/dev/tests/functional/lib/Mtf/Util/Generate/Repository/TableCollection.php
index 940de6bd0ff863bb8f3fa112e003a562d5394030..f5c9bcbe2d5049fecb43f216e504fb6eef94c149 100644
--- a/dev/tests/functional/lib/Mtf/Util/Generate/Repository/TableCollection.php
+++ b/dev/tests/functional/lib/Mtf/Util/Generate/Repository/TableCollection.php
@@ -21,7 +21,7 @@ class TableCollection extends AbstractCollection
     /**
      * @constructor
      * @param \Magento\Core\Model\EntityFactory $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param null $connection
@@ -30,7 +30,7 @@ class TableCollection extends AbstractCollection
      */
     public function __construct(
         \Magento\Core\Model\EntityFactory $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         $connection = null,
diff --git a/dev/tests/functional/phpunit.xml.dist b/dev/tests/functional/phpunit.xml.dist
index 3cfdfc5ccbdfebf2f355e672551726654d3dd077..e480294de2aa43cb4ab824f02de2f6a712a434a4 100755
--- a/dev/tests/functional/phpunit.xml.dist
+++ b/dev/tests/functional/phpunit.xml.dist
@@ -25,6 +25,7 @@
             </arguments>
         </listener>
         <listener class="Mtf\System\Event\StateListener" />
+        <listener class="Mtf\System\JUnit"/>
     </listeners>
 
     <php>
@@ -38,6 +39,7 @@
         <env name="log_directory" value="var/log" />
         <env name="events_preset" value="base" />
         <env name="module_whitelist" value="Magento_Install" />
+        <env name="report_file_name" value="test-cases-report.xml"/>
     </php>
 
 </phpunit>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
index 6402bd1873a0d6a36a0f1656cc9d0fecb43cba11..851892347af536d4c1759d6d59f8d8439582257e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php
@@ -121,9 +121,11 @@ class Tree extends Block
     protected function prepareFullCategoryPath(CatalogCategory $category)
     {
         $path = [];
-        $parentCategory = $category->getDataFieldConfig('parent_id')['source']->getParentCategory();
+        $parentCategory = $category->hasData('parent_id')
+            ? $category->getDataFieldConfig('parent_id')['source']->getParentCategory()
+            : null;
 
-        if ($parentCategory != null) {
+        if ($parentCategory !== null) {
             $path = $this->prepareFullCategoryPath($parentCategory);
         }
         return array_filter(array_merge($path, [$category->getPath(), $category->getName()]));
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory/ParentId.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory/ParentId.php
index c8f66313c0802837d2b002f799b170fddd9effe8..01ba2f41397c821367660a6b5597057f9de876d0 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory/ParentId.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory/ParentId.php
@@ -38,7 +38,7 @@ class ParentId implements FixtureInterface
     public function __construct(FixtureFactory $fixtureFactory, array $params, $data = [])
     {
         $this->params = $params;
-        if ($data['dataSet']) {
+        if (isset($data['dataSet']) && $data['dataSet'] !== '-') {
             $this->parentCategory = $fixtureFactory->createByCode('catalogCategory', ['dataSet' => $data['dataSet']]);
             if (!$this->parentCategory->hasData('id')) {
                 $this->parentCategory->persist();
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest/test.csv
index 6252e2454054cb0c40d640a3aa9bcd27449976cf..f3e9d14a6db51510344e73b3d79516ab33165a1f 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest/test.csv
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest/test.csv
@@ -1,6 +1,6 @@
 "addCategory";"category/data/parent_id/dataSet";"category/data/name";"category/data/url_key";"category/data/is_active";"category/data/description";"category/data/meta_title";"category/data/include_in_menu";"category/data/display_mode";"category/data/landing_page";"category/data/is_anchor";"category/data/available_product_listing_config";"category/data/available_sort_by/sort_0";"category/data/available_sort_by/sort_1";"category/data/available_sort_by/sort_2";"category/data/default_product_listing_config";"category/data/default_sort_by";"category/data/use_config_price_range";"category/data/layered_navigation_price_step";"category/data/category_products_data/preset";"category/data/category_products/dataSet";"constraint"
-"addRootCategory";"1";"RootCategory%isolation%";"RootCategory%isolation%";"Yes";"RootCategory Required ";"-";"-";"-";"-";"-";"No";"Position";"Name";"Price";"-";"-";"-";"-";"-";"-";"assertCategorySaveMessage, assertCategoryForm"
-"addRootCategory";"1";"RootCategory%isolation%";"RootCategory%isolation%";"Yes";"RootCategory All Fields ";"RootCategory Page Title";"Yes";"Static block and products";"Catalog Events Lister";"Yes";"No";"Position";"Name";"Price";"No";"Name";"No";"50";"-";"-";"assertCategorySaveMessage, assertCategoryForm"
+"addRootCategory";"-";"RootCategory%isolation%";"RootCategory%isolation%";"Yes";"RootCategory Required ";"-";"-";"-";"-";"-";"No";"Position";"Name";"Price";"-";"-";"-";"-";"-";"-";"assertCategorySaveMessage, assertCategoryForm"
+"addRootCategory";"-";"RootCategory%isolation%";"RootCategory%isolation%";"Yes";"RootCategory All Fields ";"RootCategory Page Title";"Yes";"Static block and products";"Catalog Events Lister";"Yes";"No";"Position";"Name";"Price";"No";"Name";"No";"50";"-";"-";"assertCategorySaveMessage, assertCategoryForm"
 "addSubcategory";"default_category";"Subcategory%isolation%";"Subcategory%isolation%";"Yes";"Subcategory Required";"-";"-";"-";"-";"-";"Yes";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertCategorySaveMessage, assertCategoryForm, assertCategoryPage"
 "addSubcategory";"default_category";"Subcategory%isolation%";"Subcategory%isolation%";"Yes";"Subcategory For Anchor Subcategory";"-";"Yes";"-";"-";"No";"Yes";"-";"-";"-";"Yes";"-";"Yes";"-";"default";"catalogProductSimple::default,catalogProductSimple::default";"assertCategorySaveMessage, assertCategoryForm, assertCategoryPage, assertCategoryForAssignedProducts"
 "addSubcategory";"default_category";"Subcategory%isolation%";"Subcategory%isolation%";"Yes";"Anchor Subcategory All Fields";"Subcategory Page Title";"Yes";"Products only";"Catalog Events Lister";"Yes";"No";"Position";"Name";"Price";"No";"Price";"No";"50";"default";"catalogProductSimple::default,catalogProductSimple::default";"assertCategorySaveMessage, assertCategoryForm, assertCategoryPage, assertCategoryForAssignedProducts"
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchResult.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchResult.php
index 03035ce728f1346e59ee891e27993f1f7782d0cc..bc0d8f4c5c5c02405076d41c8cbae89d131e6004 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchResult.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertCatalogSearchResult.php
@@ -5,11 +5,12 @@
 
 namespace Magento\CatalogSearch\Test\Constraint;
 
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
 use Magento\CatalogSearch\Test\Page\AdvancedResult;
 use Mtf\Constraint\AbstractConstraint;
 
 /**
- * Class AssertCatalogSearchResult
+ * Assert search results.
  */
 class AssertCatalogSearchResult extends AbstractConstraint
 {
@@ -18,40 +19,31 @@ class AssertCatalogSearchResult extends AbstractConstraint
     /* end tags */
 
     /**
-     * Assert that result page contains all products, according to search request, from fixture
+     * Assert that result page contains product, according to search request from fixture.
      *
-     * @param array $products
+     * @param CatalogSearchQuery $catalogSearch
      * @param AdvancedResult $resultPage
      * @return void
      */
-    public function processAssert(array $products, AdvancedResult $resultPage)
+    public function processAssert(CatalogSearchQuery $catalogSearch, AdvancedResult $resultPage)
     {
-        $errors = [];
-        foreach ($products as $product) {
-            $name = $product->getName();
+        $product = $catalogSearch->getDataFieldConfig('query_text')['source']->getProduct();
+        $name = $product->getName();
+        $isProductVisible = $resultPage->getListProductBlock()->isProductVisible($name);
+        while (!$isProductVisible && $resultPage->getBottomToolbar()->nextPage()) {
             $isProductVisible = $resultPage->getListProductBlock()->isProductVisible($name);
-            while (!$isProductVisible && $resultPage->getBottomToolbar()->nextPage()) {
-                $isProductVisible = $resultPage->getListProductBlock()->isProductVisible($name);
-            }
-
-            if ($isProductVisible === false) {
-                $errors[] = '- ' . $name;
-            }
         }
 
-        \PHPUnit_Framework_Assert::assertTrue(
-            empty($errors),
-            'Were not found the following products:' . implode("\n", $errors)
-        );
+        \PHPUnit_Framework_Assert::assertTrue($isProductVisible, "A product with name '$name' was not found.");
     }
 
     /**
-     * Returns a string representation of the object
+     * Returns a string representation of the object.
      *
      * @return string
      */
     public function toString()
     {
-        return 'All products have been successfully found.';
+        return 'Searched product has been successfully found.';
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertProductCanBeOpenedFromSearchResult.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertProductCanBeOpenedFromSearchResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..8363237b6ac44281e6e1c17427a45d7bd559e9b4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertProductCanBeOpenedFromSearchResult.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\CatalogSearch\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\CatalogSearch\Test\Page\AdvancedResult;
+use Magento\Catalog\Test\Page\Product\CatalogProductView;
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+
+/**
+ * Assert product can be opened from search results page.
+ */
+class AssertProductCanBeOpenedFromSearchResult extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'high';
+    /* end tags */
+
+    /**
+     * Assert product can be opened from search results page.
+     *
+     * @param CatalogSearchQuery $catalogSearch
+     * @param AdvancedResult $resultPage
+     * @param CatalogProductView $catalogProductViewPage
+     * @return void
+     */
+    public function processAssert(
+        CatalogSearchQuery $catalogSearch,
+        AdvancedResult $resultPage,
+        CatalogProductView $catalogProductViewPage
+    ) {
+        $product = $catalogSearch->getDataFieldConfig('query_text')['source']->getProduct();
+        $productName = $product->getName();
+        $isProductVisible = $resultPage->getListProductBlock()->isProductVisible($productName);
+        while (!$isProductVisible && $resultPage->getBottomToolbar()->nextPage()) {
+            $isProductVisible = $resultPage->getListProductBlock()->isProductVisible($productName);
+        }
+        \PHPUnit_Framework_Assert::assertTrue($isProductVisible, "A product with name $productName was not found.");
+
+        $resultPage->getListProductBlock()->openProductViewPage($productName);
+        \PHPUnit_Framework_Assert::assertEquals(
+            $productName,
+            $catalogProductViewPage->getViewBlock()->getProductName(),
+            'Wrong product page has been opened.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product can be opened from search results page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.php
index 6fa48c95845542276e6580055fbd968241ff6a94..a7cf9414dd9d514a2c8d0b08dd32a992871f70d9 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery.php
@@ -42,7 +42,7 @@ class CatalogSearchQuery extends InjectableFixture
         'is_required' => '',
         'default_value' => '',
         'input' => '',
-        'source' => 'Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery\SearchData',
+        'source' => 'Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery\QueryText',
     ];
 
     protected $num_results = [
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/QueryText.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/QueryText.php
new file mode 100644
index 0000000000000000000000000000000000000000..e570c33fa10207b205a325dff1d4ca9dddb5744c
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/QueryText.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+
+use Mtf\Fixture\FixtureFactory;
+use Mtf\Fixture\FixtureInterface;
+use Mtf\Fixture\InjectableFixture;
+
+/**
+ * Data to search for.
+ * Possible templates:
+ * - {value}
+ * - {product}::{product_property_to_search}
+ * - {product}::{product_dataSet}::{product_property_to_search}
+ */
+class QueryText implements FixtureInterface
+{
+    /**
+     * Entity to search.
+     *
+     * @var InjectableFixture
+     */
+    protected $product;
+
+    /**
+     * Resource data.
+     *
+     * @var string
+     */
+    protected $data;
+
+    /**
+     * @constructor
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param array $data
+     */
+    public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
+    {
+        $this->params = $params;
+        $explodeValue = explode('::', $data['value']);
+        if (!empty($explodeValue) && count($explodeValue) > 1) {
+            $fixtureCode = $explodeValue[0];
+            $dataSet = isset($explodeValue[2]) ? $explodeValue[1] : '';
+            $searchValue = isset($explodeValue[2]) ? $explodeValue[2] : $explodeValue[1];
+            $this->product = $fixtureFactory->createByCode($fixtureCode, ['dataSet' => $dataSet]);
+            if (!$this->product->hasData('id')) {
+                $this->product->persist();
+            }
+            if ($this->product->hasData($searchValue)) {
+                $getProperty = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $searchValue)));
+                $this->data = $this->product->$getProperty();
+            } else {
+                $this->data = $searchValue;
+            }
+        } else {
+            $this->data = strval($data['value']);
+        }
+    }
+
+    /**
+     * Persist custom selections products.
+     *
+     * @return void
+     */
+    public function persist()
+    {
+        //
+    }
+
+    /**
+     * Return prepared data.
+     *
+     * @param string|null $key
+     * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getData($key = null)
+    {
+        return $this->data;
+    }
+
+    /**
+     * Return data set configuration settings.
+     *
+     * @return array
+     */
+    public function getDataConfig()
+    {
+        return $this->params;
+    }
+
+    /**
+     * Get product fixture to search.
+     *
+     * @return InjectableFixture
+     */
+    public function getProduct()
+    {
+        return $this->product;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/SearchData.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/SearchData.php
deleted file mode 100644
index ca125d27cd216060ade515298607425a4407246b..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Fixture/CatalogSearchQuery/SearchData.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-
-namespace Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
-
-use Mtf\Fixture\FixtureFactory;
-use Mtf\Fixture\FixtureInterface;
-
-/**
- * Class SearchData
- * Data to search for
- */
-class SearchData implements FixtureInterface
-{
-    /**
-     * Resource data
-     *
-     * @var string
-     */
-    protected $data;
-
-    /**
-     * @param FixtureFactory $fixtureFactory
-     * @param array $params
-     * @param array $data
-     */
-    public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = [])
-    {
-        $this->params = $params;
-        $explodeValue = explode('::', $data['value']);
-        if (!empty($explodeValue) && count($explodeValue) > 1) {
-            /** @var FixtureInterface $fixture */
-            $fixture = $fixtureFactory->createByCode($explodeValue[0]);
-            $fixture->persist();
-            $this->data = $fixture->$explodeValue[1]();
-        } else {
-            $this->data = strval($data['value']);
-        }
-    }
-
-    /**
-     * Persist custom selections products
-     *
-     * @return void
-     */
-    public function persist()
-    {
-        //
-    }
-
-    /**
-     * Return prepared data
-     *
-     * @param string|null $key
-     * @return string
-     *
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     */
-    public function getData($key = null)
-    {
-        return $this->data;
-    }
-
-    /**
-     * Return data set configuration settings
-     *
-     * @return array
-     */
-    public function getDataConfig()
-    {
-        return $this->params;
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.php
index ac620bd1c9ebc42d3a896fd652efc728c89a2418..c3f21df8d2fff9cdae48dd9fa3fa4167a76881a6 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest.php
@@ -12,7 +12,6 @@ use Mtf\Fixture\FixtureFactory;
 use Mtf\TestCase\Injectable;
 
 /**
- * Test Flow:
  * Preconditions:
  * 1. Two specific simple product is created(unique sku,name,short/full description, tax class)
  *
@@ -29,7 +28,7 @@ use Mtf\TestCase\Injectable;
 class AdvancedSearchEntityTest extends Injectable
 {
     /**
-     * Prepare data
+     * Prepare data.
      *
      * @param FixtureFactory $fixtureFactory
      * @return array
@@ -59,18 +58,14 @@ class AdvancedSearchEntityTest extends Injectable
     }
 
     /**
-     * Run test creation for advanced search entity
+     * Run test creation for advanced search entity.
      *
-     * @param array $products
      * @param CatalogProductSimple $productSearch
      * @param CmsIndex $cmsIndex
      * @param AdvancedSearch $searchPage
      * @return void
-     *
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function test(
-        array $products,
         CatalogProductSimple $productSearch,
         CmsIndex $cmsIndex,
         AdvancedSearch $searchPage
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest/test.csv b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest/test.csv
index 687344b622bc901679dd91d607507442b506046e..76eb2b4ead571fac5a047371e29598bc85b9240e 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest/test.csv
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchEntityTest/test.csv
@@ -1,13 +1,14 @@
-"products/simple_1";"products/simple_2";"productSearch/data/name";"productSearch/data/sku";"productSearch/data/description";"productSearch/data/short_description";"productSearch/data/price/value/price_from";"productSearch/data/price/value/price_to";"constraint"
-"Yes";"-";"abc_dfj";"abc_dfj";"adc_Full";"abc_short";49;500;"assertAdvancedSearchProductsResult"
-"Yes";"-";"abc";"-";"-";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"-";"Yes";"adc_123";"-";"-";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"Yes";"-";"-";"abc";"-";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"Yes";"-";"-";"abc_dfj";"-";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"Yes";"-";"-";"abc";"adc_full";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"-";"Yes";"-";"-";"dfj_full";"-";"-";"-";"assertAdvancedSearchProductsResult"
-"Yes";"-";"-";"-";"-";"abc_short";"-";"-";"assertAdvancedSearchProductsResult"
-"-";"-";"-";"-";"-";"dfj_short";"-";"-";"assertAdvancedSearchProductsResult"
-"Yes";"-";"-";"-";"-";"-";50;50;"assertAdvancedSearchProductsResult"
-"Yes";"Yes";"-";"-";"-";"-";"-";100;"assertAdvancedSearchProductsResult"
-"Yes";"-";"abc_dfj";"abc_dfj";"adc_Full";"abc_short";49;50;"assertAdvancedSearchProductsResult"
+"description";"products/simple_1";"products/simple_2";"productSearch/data/name";"productSearch/data/sku";"productSearch/data/description";"productSearch/data/short_description";"productSearch/data/price/value/price_from";"productSearch/data/price/value/price_to";"constraint";"tag"
+"MAGETWO-12421: Use Advanced Search to Find the Product";"Yes";"-";"abc_dfj";"abc_dfj";"-";"-";"-";"-";"assertAdvancedSearchProductsResult";"bamboo_plan:end_to_end"
+"Search product in advanced search by name";"-";"Yes";"adc_123";"-";"-";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by partial name";"Yes";"-";"abc";"-";"-";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by sku";"Yes";"-";"-";"abc_dfj";"-";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by partial sku";"Yes";"-";"-";"abc";"-";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by partial sku and description";"Yes";"-";"-";"abc";"adc_full";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by description";"-";"Yes";"-";"-";"dfj_full";"-";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by short description";"-";"-";"-";"-";"-";"dfj_short";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by partial short description";"Yes";"-";"-";"-";"-";"abc_short";"-";"-";"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by price to";"Yes";"Yes";"-";"-";"-";"-";"-";100;"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by price from and price to";"Yes";"-";"-";"-";"-";"-";50;50;"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by name, sku, description, short description, price from and price to";"Yes";"-";"abc_dfj";"abc_dfj";"adc_Full";"abc_short";49;500;"assertAdvancedSearchProductsResult";""
+"Search product in advanced search by name, sku, description, short description, price from and price to";"Yes";"-";"abc_dfj";"abc_dfj";"adc_Full";"abc_short";49;50;"assertAdvancedSearchProductsResult";""
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchTest.php
deleted file mode 100644
index fe1a12168297ba1b85be61a2ba5d073714769c03..0000000000000000000000000000000000000000
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/AdvancedSearchTest.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-
-namespace Magento\CatalogSearch\Test\TestCase;
-
-use Mtf\Factory\Factory;
-use Mtf\TestCase\Functional;
-
-/**
- * Class AdvancedSearchTest
- * Searching product in the Frontend via advanced search
- */
-class AdvancedSearchTest extends Functional
-{
-    /**
-     * Advanced search product on frontend by product name
-     *
-     * @ZephyrId MAGETWO-12421
-     */
-    public function testProductSearch()
-    {
-        //Data
-        $productFixture = Factory::getFixtureFactory()->getMagentoCatalogSimpleProduct();
-        $productFixture->switchData('simple');
-        $productFixture->persist();
-
-        //Pages
-        $homePage = Factory::getPageFactory()->getCmsIndexIndex();
-        $advancedSearchPage = Factory::getPageFactory()->getCatalogsearchAdvanced();
-        $advancedSearchResultPage = Factory::getPageFactory()->getCatalogsearchResult();
-
-        //Steps
-        $homePage->open();
-        $homePage->getSearchBlock()->clickAdvancedSearchButton();
-        $searchForm = $advancedSearchPage->getForm();
-        $this->assertTrue($searchForm->isVisible(), '"Advanced Search" form is not opened');
-        $searchForm->fillCustom($productFixture, ['name', 'sku']);
-        $searchForm->submit();
-
-        //Verifying
-        $productName = $productFixture->getName();
-        $this->assertTrue(
-            $advancedSearchResultPage->getListProductBlock()->isProductVisible($productName),
-            sprintf('Product "%s" is not displayed on the "Catalog Advanced Search" results page."', $productName)
-        );
-    }
-}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c04b3e6d309f0c400a3bc1b4759bcd74c1a87cc6
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\CatalogSearch\Test\TestCase;
+
+use Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery;
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\TestCase\Injectable;
+
+/**
+ * Preconditions:
+ * 1. All product types are created.
+ *
+ * Steps:
+ * 1. Navigate to frontend on index page.
+ * 2. Input test data into "search field" and press Enter key.
+ * 3. Perform all assertions.
+ *
+ * @group Search_Frontend_(MX)
+ * @ZephyrId MAGETWO-25095
+ */
+class SearchEntityResultsTest extends Injectable
+{
+    /**
+     * CMS index page.
+     *
+     * @var CmsIndex
+     */
+    protected $cmsIndex;
+
+    /**
+     * Inject data.
+     *
+     * @param CmsIndex $cmsIndex
+     * @return void
+     */
+    public function __inject(CmsIndex $cmsIndex)
+    {
+        $this->cmsIndex = $cmsIndex;
+    }
+
+    /**
+     * Run searching result test.
+     *
+     * @param CatalogSearchQuery $catalogSearch
+     * @return void
+     */
+    public function test(CatalogSearchQuery $catalogSearch)
+    {
+        $this->cmsIndex->open();
+        $this->cmsIndex->getSearchBlock()->search($catalogSearch->getQueryText());
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest/test.csv b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f6082080c2e9390765b784f9c8a79b38d93702ec
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SearchEntityResultsTest/test.csv
@@ -0,0 +1,9 @@
+"description";"catalogSearch/data/query_text/value";"constraint";"tag"
+"MAGETWO-12420: Use Quick Search to Find the Product";"catalogProductSimple::default::sku";"assertProductCanBeOpenedFromSearchResult";"bamboo_plan:BAT"
+"Search simple product";"catalogProductSimple::default::simple";"assertCatalogSearchResult";""
+"Search virtual product";"catalogProductVirtual::default::virtual";"assertCatalogSearchResult";""
+"Search configurable product";"configurableProductInjectable::default::configurable";"assertCatalogSearchResult";""
+"Search downloadable product";"downloadableProductInjectable::default::downloadable";"assertCatalogSearchResult";""
+"Search grouped product";"groupedProductInjectable::default::grouped";"assertCatalogSearchResult";""
+"Search bundle dynamic product";"bundleProduct::bundle_dynamic_product::bundle";"assertCatalogSearchResult";""
+"Search fixed product";"bundleProduct::bundle_fixed_product::bundle";"assertCatalogSearchResult";""
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest/testSearch.csv b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest/testSearch.csv
index 2843f836b276b7fea1c7f38e2c123f88dc6e690c..73e196ce0a25fdd302e0da27117a2a477cb3dde8 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest/testSearch.csv
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/TestCase/SuggestSearchingResultEntityTest/testSearch.csv
@@ -1,3 +1,3 @@
 "catalogSearch/data/query_text/value";"catalogSearch/data/num_results";"constraint"
-"catalogProductSimple::getName";"-";"assertSuggestSearchingResult"
-"catalogProductSimple::getSku";"1";"assertSuggestSearchingResult"
+"catalogProductSimple::name";"-";"assertSuggestSearchingResult"
+"catalogProductSimple::sku";"1";"assertSuggestSearchingResult"
diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/constraint.xml b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/constraint.xml
index 5cb45afd90ea77991357b5d953997be6fa4135c3..f55277251d871dd12404a13139f51ecaed466029 100644
--- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/constraint.xml
+++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/etc/constraint.xml
@@ -119,4 +119,12 @@
             <browser class="Mtf\Client\Browser" />
         </require>
     </assertSearchSynonymMassActionNotOnFrontend>
+    <assertProductCanBeOpenedFromSearchResult module="Magento_CatalogSearch">
+        <severity>high</severity>
+        <require>
+            <catalogSearch class="Magento\CatalogSearch\Test\Fixture\CatalogSearchQuery" />
+            <resultPage class="Magento\CatalogSearch\Test\Page\AdvancedResult" />
+            <catalogProductViewPage class="Magento\Catalog\Test\Page\Product\CatalogProductView" />
+        </require>
+    </assertProductCanBeOpenedFromSearchResult>
 </constraint>
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductDuplicateForm.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductDuplicateForm.php
index 4c6ea9e268ee9db9a0d18ffbe8a111a259016406..daea7ea002c6e50fa49508da10e1e9626053674b 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductDuplicateForm.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableProductDuplicateForm.php
@@ -39,6 +39,10 @@ class AssertConfigurableProductDuplicateForm extends AssertConfigurableProductFo
         $productData = $product->getData();
         $productData['sku'] = $duplicateProductSku;
         $productData['status'] = 'Product offline';
+        if (isset($compareData['quantity_and_stock_status']['qty'])) {
+            $compareData['quantity_and_stock_status']['qty'] = '';
+            $compareData['quantity_and_stock_status']['is_in_stock'] = 'Out of Stock';
+        }
         $fixtureData = $this->prepareFixtureData($productData, $this->sortFields);
         $formData = $this->prepareFormData($productPage->getProductForm()->getData($product), $this->sortFields);
         $error = $this->verifyData($fixtureData, $formData);
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest/testCreateCustomerBackendEntity.csv b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest/testCreateCustomerBackendEntity.csv
index 47b35a7511a615f8810f922c99bd89bd59a39832..3474c0f0765579785c96ca5c4230a936514b227e 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest/testCreateCustomerBackendEntity.csv
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest/testCreateCustomerBackendEntity.csv
@@ -1,6 +1,6 @@
 "customer/data/website_id";"customer/data/group_id/dataSet";"customer/data/prefix";"customer/data/firstname";"customer/data/middlename";"customer/data/lastname";"customer/data/suffix";"customer/data/email";"customer/data/dob";"customer/data/taxvat";"customer/data/gender";"address/data/firstname";"address/data/lastname";"address/data/street";"address/data/city";"address/data/country_id";"address/data/region_id";"address/data/postcode";"address/data/telephone";"constraint"
 "Main Website";"General";"-";"John%isolation%";"-";"Doe%isolation%";"-";"JohnDoe%isolation%@example.com";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerSuccessSaveMessage, assertCustomerInGrid, assertCustomerForm"
-"Admin";"Wholesale";"M";"John%isolation%";"Jack";"Doe%isolation%";"S";"JohnDoe%isolation%@example.com";"3/16/2004";"-";"Male";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerSuccessSaveMessage, assertCustomerInGrid, assertCustomerForm"
+"Admin";"Wholesale";"M";"John%isolation%";"Jack";"Doe%isolation%";"S";"JohnDoe%isolation%@example.com";"03/16/2004";"-";"Male";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerSuccessSaveMessage, assertCustomerInGrid, assertCustomerForm"
 "Main Website";"General";"-";"John%isolation%";"-";"Doe%isolation%";"-";"JohnDoe%isolation%@example.com";"-";"-";"-";"Joe";"Doe";"1 Main Street";"Culver City";"United States";"California";"90230";"3109450345";"assertCustomerSuccessSaveMessage, assertCustomerInGrid, assertCustomerForm"
 "Main Website";"Retailer";"-";"John%isolation%";"-";"Doe%isolation%";"-";"JohnDoe%isolation%@example.ccc";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerInvalidEmail"
 "Main Website";"General";"-";"Thomas%isolation%";"-";"Oster%isolation%";"-";"Thomas%isolation%@example.com";"-";"5250008057";"-";"Thomas";"Oster";"Chmielna 113";"Bielsko-Biala";"Poland";"-";"43-310 ";"799885616";"assertCustomerSuccessSaveMessage, assertCustomerInGrid, assertCustomerForm"
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest/testUpdateCustomerBackendEntity.csv b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest/testUpdateCustomerBackendEntity.csv
index 649c9f7842c9fb4907ab8250ac9f4dc6f7e9d388..457306867243d367f992b907b83d97a5868739ee 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest/testUpdateCustomerBackendEntity.csv
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest/testUpdateCustomerBackendEntity.csv
@@ -1,4 +1,4 @@
-"initialCustomer/dataSet";"customer/data/group_id/dataSet";"customer/data/prefix";"customer/data/firstname";"customer/data/middlename";"customer/data/lastname";"customer/data/suffix";"customer/data/email";"customer/data/dob";"customer/data/taxvat";"customer/data/gender";"address/data/prefix";"address/data/firstname";"address/data/middlename";"address/data/lastname";"address/data/suffix";"address/data/company";"address/data/street";"address/data/city";"address/data/country_id";"address/data/region_id";"address/data/region";"address/data/postcode";"address/data/telephone";"address/data/fax";"address/data/vat_id";"constraint";"issue"
-"default";"Wholesale";"%isolation%Prefix_";"John_%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"JohnDoe%isolation%@example.com";1/8/1986;123456789001;"Male";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid";"Bug: MAGETWO-31689"
-"default";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"Prefix%isolation%_";"Doe%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"Company%isolation%";"3962 Horner Street";"Dothan";"United States";"Alabama";"-";36303;"334-200-4060";"555-666-777-8910";"U1234567890";"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid";""
-"default";"Retailer";"%isolation%Prefix_";"Jane_%isolation%";"Jane Middle Name %isolation%";"Doe%isolation%";"_JaneSuffix%isolation%";"Jane%isolation%@example.com";1/12/2000;987654321;"Female";"Prefix%isolation%_";"Doe%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"Company%isolation%";"39 Northgate Street";"BICKTON";"United Kingdom";"-";"PINMINNOCH";"KA26 1PF ";"999-777-111-2345";"-";987654321;"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid";""
+"initialCustomer/dataSet";"customer/data/group_id/dataSet";"customer/data/prefix";"customer/data/firstname";"customer/data/middlename";"customer/data/lastname";"customer/data/suffix";"customer/data/email";"customer/data/dob";"customer/data/taxvat";"customer/data/gender";"address/data/prefix";"address/data/firstname";"address/data/middlename";"address/data/lastname";"address/data/suffix";"address/data/company";"address/data/street";"address/data/city";"address/data/country_id";"address/data/region_id";"address/data/region";"address/data/postcode";"address/data/telephone";"address/data/fax";"address/data/vat_id";"constraint"
+"default";"Wholesale";"%isolation%Prefix_";"John_%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"JohnDoe%isolation%@example.com";01/08/1986;123456789001;"Male";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid"
+"default";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"Prefix%isolation%_";"Doe%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"Company%isolation%";"3962 Horner Street";"Dothan";"United States";"Alabama";"-";36303;"334-200-4060";"555-666-777-8910";"U1234567890";"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid"
+"default";"Retailer";"%isolation%Prefix_";"Jane_%isolation%";"Jane Middle Name %isolation%";"Doe%isolation%";"_JaneSuffix%isolation%";"Jane%isolation%@example.com";01/12/2000;987654321;"Female";"Prefix%isolation%_";"Doe%isolation%";"Middle Name %isolation%";"Doe%isolation%";"_Suffix%isolation%";"Company%isolation%";"39 Northgate Street";"BICKTON";"United Kingdom";"-";"PINMINNOCH";"KA26 1PF ";"999-777-111-2345";"-";987654321;"assertCustomerSuccessSaveMessage, assertCustomerForm, assertCustomerInGrid"
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd025b734f794d319f7c80df777057c6890d16bf
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Form;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Create Admin Account block.
+ */
+class CreateAdmin extends Form
+{
+    /**
+     * 'Next' button.
+     *
+     * @var string
+     */
+    protected $next = "[ng-click*='next']";
+
+    /**
+     * Click on 'Next' button.
+     *
+     * @return void
+     */
+    public function clickNext()
+    {
+        $this->_rootElement->find($this->next, Locator::SELECTOR_CSS)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..87f9389c51434d6bcb9462412788f45ed2f7f6c0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CreateAdmin.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <username>
+            <selector>[name='adminUsername']</selector>
+        </username>
+        <email>
+            <selector>[name='adminEmail']</selector>
+        </email>
+        <password>
+            <selector>[name='adminPassword']</selector>
+        </password>
+        <password_confirmation>
+            <selector>[name='adminConfirm']</selector>
+        </password_confirmation>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.php
new file mode 100644
index 0000000000000000000000000000000000000000..af5707450b52e1cd068fc331b09a49ba9364a6ea
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Form;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Customize Your Store block.
+ */
+class CustomizeStore extends Form
+{
+    /**
+     * 'Next' button.
+     *
+     * @var string
+     */
+    protected $next = "[ng-click*='next']";
+
+    /**
+     * Click on 'Next' button.
+     *
+     * @return void
+     */
+    public function clickNext()
+    {
+        $this->_rootElement->find($this->next, Locator::SELECTOR_CSS)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.xml
new file mode 100644
index 0000000000000000000000000000000000000000..afca361627a82e77d04da2a9c2c9102eadb5688b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/CustomizeStore.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <currency>
+            <selector>[ng-model*='currency']</selector>
+            <input>select</input>
+        </currency>
+        <language>
+            <selector>[ng-model*='language']</selector>
+            <input>select</input>
+        </language>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d5919a7ec93110c43152846098ac179c9353606
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Form;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Database form.
+ */
+class Database extends Form
+{
+    /**
+     * 'Test connection successful.' message.
+     *
+     * @var string
+     */
+    protected $successConnectionMessage = ".text-success";
+
+    /**
+     * 'Next' button.
+     *
+     * @var string
+     */
+    protected $next = "[ng-click*='testConnection']";
+
+    /**
+     * Get 'Test connection successful.' message.
+     *
+     * @return string
+     */
+    public function getSuccessConnectionMessage()
+    {
+        return $this->_rootElement->find($this->successConnectionMessage, Locator::SELECTOR_CSS)->getText();
+    }
+
+    /**
+     * Click on 'Next' button.
+     *
+     * @return void
+     */
+    public function clickNext()
+    {
+        $this->_rootElement->find($this->next, Locator::SELECTOR_CSS)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c09b95b5d282e8b04a12137f7c2921ebd7cb7e11
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Database.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <dbHost />
+        <dbUser />
+        <dbPassword />
+        <dbName>
+            <selector>[name="dbname"]</selector>
+        </dbName>
+        <dbTablePrefix />
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Install.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Install.php
new file mode 100644
index 0000000000000000000000000000000000000000..8df7ca8d6c0c288cfd25b9e7d84a843d82207a3e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Install.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Install block.
+ */
+class Install extends Block
+{
+    /**
+     * 'Install Now' button.
+     *
+     * @var string
+     */
+    protected $installNow = "//*[@ng-show='!isStarted']/button";
+
+    /**
+     * Admin info block.
+     *
+     * @var string
+     */
+    protected $adminInfo = "//*[@id='admin-info']";
+
+    /**
+     * Database info block.
+     *
+     * @var string
+     */
+    protected $dbInfo = "//*[@id='db-info']";
+
+    /**
+     * 'Launch Magento Admin' button.
+     *
+     * @var string
+     */
+    protected $launchAdmin = "//*[@type='button']";
+
+    /**
+     * Click on 'Install Now' button.
+     *
+     * @return void
+     */
+    public function clickInstallNow()
+    {
+        $this->_rootElement->find($this->installNow, Locator::SELECTOR_XPATH)->click();
+        $this->waitForElementVisible($this->launchAdmin, Locator::SELECTOR_XPATH);
+    }
+
+    /**
+     * Get admin info.
+     *
+     * @return string
+     */
+    public function getAdminInfo()
+    {
+        $adminData = [];
+        $rows = $this->_rootElement->find('#admin-info .row')->getElements();
+        foreach ($rows as $row) {
+            $dataRow = $row->find('div')->getElements();
+            $key = strtolower(str_replace(' ', '_', str_replace(':', '', $dataRow[0]->getText())));
+            $adminData[$key] = $dataRow[1]->getText();
+        }
+
+        return $adminData;
+    }
+
+    /**
+     * Get database info.
+     *
+     * @return string
+     */
+    public function getDbInfo()
+    {
+        $dbData = [];
+        $rows = $this->_rootElement->find('#db-info .row')->getElements();
+        foreach ($rows as $row) {
+            $dataRow = $row->find('div')->getElements();
+            $key = strtolower(str_replace(' ', '_', str_replace(':', '', $dataRow[0]->getText())));
+            $dbData[$key] = $dataRow[1]->getText();
+        }
+
+        return $dbData;
+    }
+
+    /**
+     * Click on 'Launch Magento Admin' button.
+     *
+     * @return void
+     */
+    public function clickLaunchAdmin()
+    {
+        $this->_rootElement->find($this->launchAdmin, Locator::SELECTOR_XPATH)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php
new file mode 100644
index 0000000000000000000000000000000000000000..75085d53c750703e95145647ba1298777a539730
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Landing.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Landing block.
+ */
+class Landing extends Block
+{
+    /**
+     * 'Agree and Set up Magento' button.
+     *
+     * @var string
+     */
+    protected $agreeAndSetup = '.btn-lg.btn-primary';
+
+    /**
+     * 'Terms & Agreement' link.
+     *
+     * @var string
+     */
+    protected $termsAndAgreement = "[ng-click*='previous']";
+
+    /**
+     * Click on 'Agree and Set up Magento' button.
+     *
+     * @return void
+     */
+    public function clickAgreeAndSetup()
+    {
+        $this->_rootElement->find($this->agreeAndSetup, Locator::SELECTOR_CSS)->click();
+    }
+
+    /**
+     * Click on 'Terms & Agreement' link.
+     *
+     * @return void
+     */
+    public function clickTermsAndAgreement()
+    {
+        $this->_rootElement->find($this->termsAndAgreement, Locator::SELECTOR_CSS)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/License.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/License.php
new file mode 100644
index 0000000000000000000000000000000000000000..83f59f7159d4d81dd0c891877268ed9bbd52ad77
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/License.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+
+/**
+ * License block.
+ */
+class License extends Block
+{
+    /**
+     * 'Back' button.
+     *
+     * @var string
+     */
+    protected $back = '.btn.btn-primary';
+
+    /**
+     * License text.
+     *
+     * @var string
+     */
+    protected $license = '.container.ng-scope';
+
+    /**
+     * Click on 'Back' button.
+     *
+     * @return void
+     */
+    public function clickBack()
+    {
+        $this->_rootElement->find($this->back, Locator::SELECTOR_CSS)->click();
+    }
+
+    /**
+     * Get license text.
+     *
+     * @return string
+     */
+    public function getLicense()
+    {
+        return $this->_rootElement->find($this->license, Locator::SELECTOR_CSS)->getText();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/Readiness.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Readiness.php
new file mode 100644
index 0000000000000000000000000000000000000000..72fcfcb1aa26ae7139e77972307a9f5373642201
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/Readiness.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Block;
+use Mtf\Client\Element\Locator;
+
+/**
+ * Readiness block.
+ */
+class Readiness extends Block
+{
+    /**
+     * 'Start Readiness Check' button.
+     *
+     * @var string
+     */
+    protected $readinessCheck = "[ng-click*='state.go']";
+
+    /**
+     * 'Next' button.
+     *
+     * @var string
+     */
+    protected $next = "[ng-click*='next']";
+
+    /**
+     * 'Completed!' message.
+     * [ng-switch-when="true"]
+     * @var string
+     */
+    protected $completedMessage = '[ng-switch-when="true"]';
+
+    /**
+     * PHP Version successful check.
+     *
+     * @var string
+     */
+    protected $phpVersionCheck = '#php-version';
+
+    /**
+     * PHP Extensions successful check.
+     *
+     * @var string
+     */
+    protected $phpExtensionCheck = '#php-extensions';
+
+    /**
+     * File Permission check.
+     *
+     * @var string
+     */
+    protected $filePermissionCheck = '#php-permissions';
+
+    /**
+     * Click on 'Start Readiness Check' button.
+     *
+     * @return void
+     */
+    public function clickReadinessCheck()
+    {
+        $this->_rootElement->find($this->readinessCheck, Locator::SELECTOR_CSS)->click();
+        $this->waitForElementVisible($this->completedMessage, Locator::SELECTOR_CSS);
+    }
+
+    /**
+     * Click on 'Next' button.
+     *
+     * @return void
+     */
+    public function clickNext()
+    {
+        $this->_rootElement->find($this->next, Locator::SELECTOR_CSS)->click();
+    }
+
+    /**
+     * Get File Permissions check result.
+     *
+     * @return string
+     */
+    public function getFilePermissionCheck()
+    {
+        return $this->_rootElement->find($this->filePermissionCheck, Locator::SELECTOR_CSS)->getText();
+    }
+
+    /**
+     * Get PHP Version check result.
+     *
+     * @return string
+     */
+    public function getPhpVersionCheck()
+    {
+        return $this->_rootElement->find($this->phpVersionCheck, Locator::SELECTOR_CSS)->getText();
+    }
+
+    /**
+     * Get PHP Extensions check result.
+     *
+     * @return string
+     */
+    public function getPhpExtensionsCheck()
+    {
+        return $this->_rootElement->find($this->phpExtensionCheck, Locator::SELECTOR_CSS)->getText();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php
new file mode 100644
index 0000000000000000000000000000000000000000..08ca27d4d6f98ef8bfc77dd58c810a0162281454
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Block;
+
+use Mtf\Block\Form;
+
+/**
+ * Web configuration block.
+ */
+class WebConfiguration extends Form
+{
+    /**
+     * 'Next' button.
+     *
+     * @var string
+     */
+    protected $next = "[ng-click*='next']";
+
+    /**
+     * 'Advanced Options' locator.
+     *
+     * @var string
+     */
+    protected $advancedOptions = "[ng-click*='advanced']";
+
+    /**
+     * Click on 'Next' button.
+     *
+     * @return void
+     */
+    public function clickNext()
+    {
+        $this->_rootElement->find($this->next)->click();
+    }
+
+    /**
+     * Click on 'Advanced Options' button.
+     *
+     * @return void
+     */
+    public function clickAdvancedOptions()
+    {
+        $this->_rootElement->find($this->advancedOptions)->click();
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.xml
new file mode 100644
index 0000000000000000000000000000000000000000..06cdb68f1bc0a0660c2075b23acc1045f03baca8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Block/WebConfiguration.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<mapping strict="0">
+    <fields>
+        <web />
+        <admin />
+        <keyOwn>
+            <selector>[value="user"]</selector>
+            <input>checkbox</input>
+        </keyOwn>
+        <keyValue>
+            <selector>[name="key"]</selector>
+        </keyValue>
+        <apacheRewrites>
+            <selector>[ng-model*="rewrites"]</selector>
+            <input>checkbox</input>
+        </apacheRewrites>
+        <httpsFront>
+            <selector>[ng-model*="front"]</selector>
+            <input>checkbox</input>
+        </httpsFront>
+        <https />
+        <httpsAdmin>
+            <selector>[type="checkbox"][ng-model*="admin"]</selector>
+            <input>checkbox</input>
+        </httpsAdmin>
+    </fields>
+</mapping>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertAgreementTextPresent.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertAgreementTextPresent.php
new file mode 100644
index 0000000000000000000000000000000000000000..673956def75bf25d20720abe50d65336081fcf04
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertAgreementTextPresent.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\Install\Test\Page\Install;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Check that agreement text present on Terms & Agreement page during install.
+ */
+class AssertAgreementTextPresent extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Part of license agreement text.
+     */
+    const LICENSE_AGREEMENT_TEXT = 'Open Software License ("OSL") v. 3.0';
+
+    /**
+     * Assert that part of license agreement text is present on Terms & Agreement page.
+     *
+     * @param Install $installPage
+     * @return void
+     */
+    public function processAssert(Install $installPage)
+    {
+        \PHPUnit_Framework_Assert::assertContains(
+            self::LICENSE_AGREEMENT_TEXT,
+            $installPage->getLicenseBlock()->getLicense(),
+            'License agreement text is absent.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "License agreement text is present on Terms & Agreement page.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertCurrencySelected.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertCurrencySelected.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2da3668ba26f38effa9ffca1691caee2b0a359a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertCurrencySelected.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that selected currency symbol displays in admin.
+ */
+class AssertCurrencySelected extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that selected currency symbol displays on dashboard.
+     *
+     * @param string $currencySymbol
+     * @param Dashboard $dashboardPage
+     * @return void
+     */
+    public function processAssert($currencySymbol, Dashboard $dashboardPage)
+    {
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($dashboardPage->getMainBlock()->getRevenuePrice(), $currencySymbol) !== false,
+            'Selected currency symbol not displays on dashboard.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Selected currency displays in admin.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertKeyCreated.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertKeyCreated.php
new file mode 100644
index 0000000000000000000000000000000000000000..13cd5642be416b2d691d019eb7ef1bbfeca64929
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertKeyCreated.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Install\Test\Page\Install;
+use Magento\Install\Test\Fixture\Install as InstallConfig;
+
+/**
+ * Assert that selected encryption key displays on success full install page.
+ */
+class AssertKeyCreated extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that selected encryption key displays on success full install page.
+     *
+     * @param Install $installPage
+     * @param InstallConfig $installConfig
+     * @return void
+     */
+    public function processAssert(Install $installPage, InstallConfig $installConfig)
+    {
+        \PHPUnit_Framework_Assert::assertEquals(
+            $installConfig->getKeyValue(),
+            $installPage->getInstallBlock()->getAdminInfo()['encryption_key'],
+            'Selected encryption key on install page not equals to data from fixture.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Selected encryption key displays on success full install page.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertLanguageSelected.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertLanguageSelected.php
new file mode 100644
index 0000000000000000000000000000000000000000..177673c0adb935bba5311d02521377b7d1f28f64
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertLanguageSelected.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Assert that selected language currently displays on frontend.
+ */
+class AssertLanguageSelected extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that selected language currently displays on frontend.
+     *
+     * @param string $languageTemplate
+     * @param CmsIndex $indexPage
+     * @return void
+     */
+    public function processAssert($languageTemplate, CmsIndex $indexPage)
+    {
+        $indexPage->open();
+        \PHPUnit_Framework_Assert::assertTrue(
+            $indexPage->getLinksBlock()->isLinkVisible($languageTemplate),
+            'Selected language not displays on frontend.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Selected language currently displays on frontend.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertRewritesEnabled.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertRewritesEnabled.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9db0e7d4a2874f9366368c6762e6ecf76db2e3f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertRewritesEnabled.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Mtf\Constraint\AbstractConstraint;
+use Mtf\Client\Driver\Selenium\Browser;
+use Magento\Catalog\Test\Fixture\CatalogCategory;
+
+/**
+ * Assert that apache redirect correct works.
+ */
+class AssertRewritesEnabled extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that apache redirect works by opening category page and asserting index.php in its url
+     *
+     * @param CatalogCategory $category
+     * @param CmsIndex $homePage
+     * @param Browser $browser
+     */
+    public function processAssert(CatalogCategory $category, CmsIndex $homePage, Browser $browser)
+    {
+        $category->persist();
+        $homePage->open();
+        $homePage->getTopmenu()->selectCategoryByName($category->getName());
+
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($browser->getUrl(), 'index.php') === false,
+            'Apache redirect for category does not work.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Apache redirect works correct.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSecureUrlEnabled.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSecureUrlEnabled.php
new file mode 100644
index 0000000000000000000000000000000000000000..2397ad0103ecd8689a7cb7f74f21b6149eb93313
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSecureUrlEnabled.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Mtf\Client\Browser;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Backend\Test\Page\Adminhtml\Dashboard;
+use Magento\Customer\Test\Page\CustomerAccountLogin;
+
+/**
+ * Assert that Secure Urls Enabled.
+ */
+class AssertSecureUrlEnabled extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'low';
+    /* end tags */
+
+    /**
+     * Assert that Secure Urls Enabled.
+     *
+     * @param Browser $browser
+     * @param Dashboard $dashboard
+     * @param CustomerAccountLogin $customerAccountLogin
+     * @return void
+     */
+    public function processAssert(
+        Browser $browser,
+        Dashboard $dashboard,
+        CustomerAccountLogin $customerAccountLogin
+    ) {
+        $dashboard->open();
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($browser->getUrl(), 'https://') !== false,
+            'Secure Url is not displayed on backend.'
+        );
+
+        $customerAccountLogin->open();
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($browser->getUrl(), 'https://') !== false,
+            'Secure Url is not displayed on frontend.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Secure Urls are displayed successful.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php
new file mode 100644
index 0000000000000000000000000000000000000000..47df11f0aaceae2a9cce48658aaa04eb68390c3f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessInstall.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\User\Test\Fixture\User;
+use Magento\Install\Test\Page\Install;
+use Mtf\Constraint\AbstractConstraint;
+use Magento\Install\Test\Fixture\Install as InstallConfig;
+
+/**
+ * Check that Magento successfully installed.
+ */
+class AssertSuccessInstall extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'high';
+    /* end tags */
+
+    /**
+     * Admin info fields mapping.
+     *
+     * @var array
+     */
+    protected $adminFieldsList = [
+        ['pageData' => 'username', 'fixture' => 'username'],
+        ['pageData' => 'e-mail', 'fixture' => 'email'],
+        ['pageData' => 'your_store_address', 'fixture' => 'web'],
+        ['pageData' => 'magento_admin_address', 'fixture' => 'admin']
+    ];
+
+    /**
+     * Database info fields mapping.
+     *
+     * @var array
+     */
+    protected $dbFieldsList = [
+        ['pageData' => 'database_name', 'fixture' => 'dbName'],
+        ['pageData' => 'username', 'fixture' => 'dbUser']
+    ];
+
+    /**
+     * Assert that Magento successfully installed.
+     *
+     * @param InstallConfig $installConfig
+     * @param User $user
+     * @param Install $installPage
+     * @return void
+     */
+    public function processAssert(Install $installPage, InstallConfig $installConfig, User $user)
+    {
+        $adminData = $installPage->getInstallBlock()->getAdminInfo();
+        $dbData = $installPage->getInstallBlock()->getDbInfo();
+
+        $allData = array_merge($user->getData(), $installConfig->getData());
+        $allData['admin'] = $allData['web'] . $allData['admin'] . '/';
+
+        foreach ($this->adminFieldsList as $field) {
+            \PHPUnit_Framework_Assert::assertEquals(
+                $allData[$field['fixture']],
+                $adminData[$field['pageData']],
+                'Wrong admin information is displayed.'
+            );
+        }
+        foreach ($this->dbFieldsList as $field) {
+            \PHPUnit_Framework_Assert::assertEquals(
+                $allData[$field['fixture']],
+                $dbData[$field['pageData']],
+                'Wrong database information is displayed.'
+            );
+        }
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "Install successfully finished.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessfulReadinessCheck.php b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessfulReadinessCheck.php
new file mode 100644
index 0000000000000000000000000000000000000000..de613def6e2c97c098a038eca938a8c16e527d90
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Constraint/AssertSuccessfulReadinessCheck.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Constraint;
+
+use Magento\Install\Test\Page\Install;
+use Mtf\Constraint\AbstractConstraint;
+
+/**
+ * Check that PHP Version, PHP Extensions and File Permission are ok.
+ */
+class AssertSuccessfulReadinessCheck extends AbstractConstraint
+{
+    /* tags */
+    const SEVERITY = 'high';
+    /* end tags */
+
+    /**
+     * PHP version message.
+     */
+    const PHP_VERSION_MESSAGE = 'Your PHP version is correct';
+
+    /**
+     * PHP extensions message.
+     */
+    const PHP_EXTENSIONS_MESSAGE = 'You meet 9 out of 9 PHP extensions requirements.';
+
+    /**
+     * File permission message.
+     */
+    const FILE_PERMISSION_MESSAGE = 'You meet 4 out of 4 writable file permission requirements.';
+
+    /**
+     * Assert that PHP Version, PHP Extensions and File Permission are ok.
+     *
+     * @param Install $installPage
+     * @return void
+     */
+    public function processAssert(Install $installPage)
+    {
+        \PHPUnit_Framework_Assert::assertContains(
+            self::PHP_VERSION_MESSAGE,
+            $installPage->getReadinessBlock()->getPhpVersionCheck(),
+            'PHP version is incorrect.'
+        );
+        \PHPUnit_Framework_Assert::assertContains(
+            self::PHP_EXTENSIONS_MESSAGE,
+            $installPage->getReadinessBlock()->getPhpExtensionsCheck(),
+            'PHP extensions missed.'
+        );
+        \PHPUnit_Framework_Assert::assertContains(
+            self::FILE_PERMISSION_MESSAGE,
+            $installPage->getReadinessBlock()->getFilePermissionCheck(),
+            'File permissions does not meet requirements.'
+        );
+    }
+
+    /**
+     * Returns a string representation of successful assertion.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return "PHP Version, PHP Extensions and File Permission are ok.";
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.php b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.php
new file mode 100644
index 0000000000000000000000000000000000000000..deec331975f74321f5298d7f51ba341041074981
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\Fixture;
+
+use Mtf\Fixture\InjectableFixture;
+
+/**
+ * Class Install
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
+ */
+class Install extends InjectableFixture
+{
+    /**
+     * @var string
+     */
+    protected $repositoryClass = 'Magento\Install\Test\Repository\Install';
+
+    /**
+     * @var string
+     */
+    protected $handlerInterface = 'Magento\Install\Test\Handler\Install\InstallInterface';
+
+    protected $defaultDataSet = [
+    ];
+
+    protected $dbHost = [
+        'attribute_code' => 'dbHost',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $dbUser = [
+        'attribute_code' => 'dbUser',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $dbPassword = [
+        'attribute_code' => 'dbPassword',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $dbName = [
+        'attribute_code' => 'dbName',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $web = [
+        'attribute_code' => 'web',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $admin = [
+        'attribute_code' => 'admin',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $adminUsername = [
+        'attribute_code' => 'adminUsername',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $adminEmail = [
+        'attribute_code' => 'adminEmail',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $adminPassword = [
+        'attribute_code' => 'adminPassword',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $adminConfirm = [
+        'attribute_code' => 'adminConfirm',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $apacheRewrites = [
+        'attribute_code' => 'apacheRewrites',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $dbTablePrefix = [
+        'attribute_code' => 'dbTablePrefix',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $keyOwn = [
+        'attribute_code' => 'keyOwn',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $httpsAdmin = [
+        'attribute_code' => 'httpsAdmin',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $https = [
+        'attribute_code' => 'https',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $httpsFront = [
+        'attribute_code' => 'httpsFront',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $keyValue = [
+        'attribute_code' => 'keyValue',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $language = [
+        'attribute_code' => 'language',
+        'backend_type' => 'virtual',
+    ];
+
+    protected $currency = [
+        'attribute_code' => 'language',
+        'backend_type' => 'virtual',
+    ];
+
+    public function getDbHost()
+    {
+        return $this->getData('dbHost');
+    }
+
+    public function getDbUser()
+    {
+        return $this->getData('dbUser');
+    }
+
+    public function getDbPassword()
+    {
+        return $this->getData('dbPassword');
+    }
+
+    public function getDbName()
+    {
+        return $this->getData('dbName');
+    }
+
+    public function getWeb()
+    {
+        return $this->getData('web');
+    }
+
+    public function getAdmin()
+    {
+        return $this->getData('admin');
+    }
+
+    public function getAdminUsername()
+    {
+        return $this->getData('adminUsername');
+    }
+
+    public function getAdminEmail()
+    {
+        return $this->getData('adminEmail');
+    }
+
+    public function getAdminPassword()
+    {
+        return $this->getData('adminPassword');
+    }
+
+    public function getAdminConfirm()
+    {
+        return $this->getData('adminConfirm');
+    }
+
+    public function getCurrency()
+    {
+        return $this->getData('currency');
+    }
+
+    public function getApacheRewrites()
+    {
+        return $this->getData('apacheRewrites');
+    }
+
+    public function getKeyOwn()
+    {
+        return $this->getData('keyOwn');
+    }
+
+    public function getKeyValue()
+    {
+        return $this->getData('keyValue');
+    }
+
+    public function getLanguage()
+    {
+        return $this->getData('language');
+    }
+
+    public function getHttpsAdmin()
+    {
+        return $this->getData('httpsAdmin');
+    }
+
+    public function getHttps()
+    {
+        return $this->getData('https');
+    }
+
+    public function getHttpsFront()
+    {
+        return $this->getData('httpsFront');
+    }
+
+    public function getDbTablePrefix()
+    {
+        return $this->getData('dbTablePrefix');
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fffac95c703866547a075593e603d4f506fd3ae1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Fixture/Install.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<fixture class="Magento\Install\Test\Fixture\Install">
+    <module>Magento_Install</module>
+    <type>virtual</type>
+    <entity_type>install</entity_type>
+    <fields>
+        <dbHost>
+            <attribute_code>dbHost</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbHost>
+        <dbUser>
+            <attribute_code>dbUser</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbUser>
+        <dbTablePrefix>
+            <attribute_code>dbTablePrefix</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbTablePrefix>
+        <dbPassword>
+            <attribute_code>dbPassword</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbPassword>
+        <dbName>
+            <attribute_code>dbname</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbName>
+        <web>
+            <attribute_code>web</attribute_code>
+            <backend_type>virtual</backend_type>
+        </web>
+        <dbTablePrefix>
+            <attribute_code>dbTablePrefix</attribute_code>
+            <backend_type>virtual</backend_type>
+        </dbTablePrefix>
+        <admin>
+            <attribute_code>admin</attribute_code>
+            <backend_type>virtual</backend_type>
+        </admin>
+        <httpsFront>
+            <attribute_code>httpsFront</attribute_code>
+            <backend_type>virtual</backend_type>
+        </httpsFront>
+        <https>
+            <attribute_code>https</attribute_code>
+            <backend_type>virtual</backend_type>
+        </https>
+        <httpsAdmin>
+            <attribute_code>httpsAdmin</attribute_code>
+            <backend_type>virtual</backend_type>
+        </httpsAdmin>
+        <apacheRewrites>
+            <attribute_code>apacheRewrites</attribute_code>
+            <backend_type>virtual</backend_type>
+        </apacheRewrites>
+        <keyOwn>
+            <attribute_code>keyOwn</attribute_code>
+            <backend_type>virtual</backend_type>
+        </keyOwn>
+        <keyValue>
+            <attribute_code>keyValue</attribute_code>
+            <backend_type>virtual</backend_type>
+        </keyValue>
+        <language>
+            <attribute_code>language</attribute_code>
+            <backend_type>virtual</backend_type>
+        </language>
+        <currency>
+            <attribute_code>currency</attribute_code>
+            <backend_type>virtual</backend_type>
+        </currency>
+    </fields>
+    <repository_class>Magento\Install\Test\Repository\Install</repository_class>
+    <handler_interface>Magento\Install\Test\Handler\Install\InstallInterface</handler_interface>
+</fixture>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/Page/Install.xml b/dev/tests/functional/tests/app/Magento/Install/Test/Page/Install.xml
new file mode 100644
index 0000000000000000000000000000000000000000..06f3b3a33b408c248a9865b82450d367765eeee3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/Page/Install.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<page mca="setup/" module="Magento_Install">
+    <blocks>
+        <landingBlock>
+            <class>Magento\Install\Test\Block\Landing</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </landingBlock>
+        <licenseBlock>
+            <class>Magento\Install\Test\Block\License</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </licenseBlock>
+        <readinessBlock>
+            <class>Magento\Install\Test\Block\Readiness</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </readinessBlock>
+        <databaseBlock>
+            <class>Magento\Install\Test\Block\Database</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </databaseBlock>
+        <webConfigBlock>
+            <class>Magento\Install\Test\Block\WebConfiguration</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </webConfigBlock>
+        <customizeStoreBlock>
+            <class>Magento\Install\Test\Block\CustomizeStore</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </customizeStoreBlock>
+        <createAdminBlock>
+            <class>Magento\Install\Test\Block\CreateAdmin</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </createAdminBlock>
+        <installBlock>
+            <class>Magento\Install\Test\Block\Install</class>
+            <locator>body</locator>
+            <strategy>css selector</strategy>
+        </installBlock>
+    </blocks>
+</page>
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2aa869b7750465d27fec6a260e88256f2e320a8a
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Install\Test\TestCase;
+
+use Magento\Cms\Test\Page\CmsIndex;
+use Magento\Install\Test\Page\Install;
+use Magento\Install\Test\Fixture\Install as InstallConfig;
+use Magento\User\Test\Fixture\User;
+use Mtf\Fixture\FixtureFactory;
+use Mtf\TestCase\Injectable;
+use Mtf\System\Config;
+use Magento\Install\Test\Constraint\AssertAgreementTextPresent;
+use Magento\Install\Test\Constraint\AssertSuccessfulReadinessCheck;
+
+/**
+ * PLEASE ADD NECESSARY INFO BEFORE RUNNING TEST TO
+ * ../dev/tests/functional/config/install_data.yml.dist
+ *
+ * Test Flow:
+ *
+ * Preconditions:
+ * 1. Uninstall Magento.
+ *
+ * Steps:
+ * 1. Go setup landing page.
+ * 2. Click on "Terms and agreements" button.
+ * 3. Check license agreement text.
+ * 4. Return back to landing page and click "Agree and Setup" button.
+ * 5. Click "Start Readiness Check" button.
+ * 6. Make sure PHP Version, PHP Extensions and File Permission are ok.
+ * 7. Click "Next" and fill DB credentials.
+ * 8. Click "Test Connection and Authentication" and make sure connection successful.
+ * 9. Click "Next" and fill store address and admin path.
+ * 10. Click "Next" and leave all default values.
+ * 11. Click "Next" and fill admin user info.
+ * 12. Click "Next" and on the "Step 6: Install" page click "Install Now" button.
+ * 13. Perform assertions.
+ *
+ * @group Installer_and_Upgrade/Downgrade_(PS)
+ * @ZephyrId MAGETWO-31431
+ */
+class InstallTest extends Injectable
+{
+    /**
+     * Install page.
+     *
+     * @var Install
+     */
+    protected $installPage;
+
+    /**
+     * Cms index page.
+     *
+     * @var CmsIndex
+     */
+    protected $homePage;
+
+    /**
+     * Uninstall Magento before test.
+     *
+     * @param Config $systemConfig
+     * @return array
+     */
+    public function __prepare(Config $systemConfig)
+    {
+        // Prepare config data
+        $configData = $systemConfig->getConfigParam('install_data/db_credentials');
+        $urlConfig = $systemConfig->getConfigParam('install_data/url');
+        $configData['web'] = $urlConfig['base_url'];
+        $configData['admin'] = $urlConfig['backend_frontname'];
+
+        return ['configData' => $configData];
+    }
+
+    /**
+     * Injection data.
+     *
+     * @param CmsIndex $homePage
+     * @param Install $installPage
+     * @return void
+     */
+    public function __inject(Install $installPage, CmsIndex $homePage)
+    {
+        $magentoBaseDir = dirname(dirname(dirname(MTF_BP)));
+        // Uninstall Magento.
+        shell_exec("php -f $magentoBaseDir/setup/index.php uninstall");
+        $this->installPage = $installPage;
+        $this->homePage = $homePage;
+    }
+
+    /**
+     * Install Magento via web interface.
+     *
+     * @param User $user
+     * @param array $install
+     * @param array $configData
+     * @param FixtureFactory $fixtureFactory
+     * @param AssertAgreementTextPresent $assertLicense
+     * @param AssertSuccessfulReadinessCheck $assertReadiness
+     * @return array
+     */
+    public function test(
+        User $user,
+        array $install,
+        array $configData,
+        FixtureFactory $fixtureFactory,
+        AssertAgreementTextPresent $assertLicense,
+        AssertSuccessfulReadinessCheck $assertReadiness
+    ) {
+        $dataConfig = array_merge($install, $configData);
+        if ($dataConfig['httpsFront'] != "-") {
+            $dataConfig['https'] = str_replace('http', 'https', $dataConfig['web']);
+        }
+        /** @var InstallConfig $installConfig */
+        $installConfig = $fixtureFactory->create('Magento\Install\Test\Fixture\Install', ['data' => $dataConfig]);
+        // Steps
+        $this->homePage->open();
+        // Verify license agreement.
+        $this->installPage->getLandingBlock()->clickTermsAndAgreement();
+        $assertLicense->processAssert($this->installPage);
+        $this->installPage->getLicenseBlock()->clickBack();
+        $this->installPage->getLandingBlock()->clickAgreeAndSetup();
+        // Step 1: Readiness Check.
+        $this->installPage->getReadinessBlock()->clickReadinessCheck();
+        $assertReadiness->processAssert($this->installPage);
+        $this->installPage->getReadinessBlock()->clickNext();
+        // Step 2: Add a Database.
+        $this->installPage->getDatabaseBlock()->fill($installConfig);
+        $this->installPage->getDatabaseBlock()->clickNext();
+        // Step 3: Web Configuration.
+        $this->installPage->getWebConfigBlock()->clickAdvancedOptions();
+        $this->installPage->getWebConfigBlock()->fill($installConfig);
+        $this->installPage->getWebConfigBlock()->clickNext();
+        // Step 4: Customize Your Store
+        $this->installPage->getCustomizeStoreBlock()->fill($installConfig);
+        $this->installPage->getCustomizeStoreBlock()->clickNext();
+        // Step 5: Create Admin Account.
+        $this->installPage->getCreateAdminBlock()->fill($user);
+        $this->installPage->getCreateAdminBlock()->clickNext();
+        // Step 6: Install.
+        $this->installPage->getInstallBlock()->clickInstallNow();
+
+        return ['installConfig' => $installConfig];
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest/test.csv b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..63ad72c17f75117c18631cb09658b51a3b0c76a8
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/TestCase/InstallTest/test.csv
@@ -0,0 +1,7 @@
+"user/dataSet";"install/dbTablePrefix";"install/admin";"install/httpsFront";"install/httpsAdmin";"install/apacheRewrites";"install/keyOwn";"install/keyValue";"install/language";"install/currency";"currencySymbol";"languageTemplate";"constraint";"description"
+"default";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertSuccessInstall, assertUserSuccessLogin";"install with default values"
+"default";"-";"custom";"-";"-";"-";"-";"-";"-";"-";"-";"-";"assertSuccessInstall, assertUserSuccessLogin";"install with custom admin path"
+"default";"-";"-";"-";"-";"-";"Yes";"123123qa";"German (Germany)";"Euro (EUR)";"€";"Suchbegriffe";"assertSuccessInstall, assertKeyCreated, assertUserSuccessLogin, assertCurrencySelected, assertLanguageSelected";"install with custom encryption key and changed currency and locale"
+"default";"prefix1_";"-";"-";"-";"-";"-";"-";"Chinese (China)";"-";"-";"-";"assertSuccessInstall, assertUserSuccessLogin";"install with table prefix"
+"default";"-";"-";"-";"-";"Yes";"-";"-";"-";"-";"-";"-";"assertSuccessInstall, assertUserSuccessLogin, assertRewritesEnabled";"install with enabled url rewrites"
+"default";"-";"-";"Yes";"Yes";"-";"-";"-";"-";"-";"-";"-";"assertSuccessInstall, assertUserSuccessLogin, assertSecureUrlEnabled";"install with enabled secure urls"
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/etc/constraint.xml b/dev/tests/functional/tests/app/Magento/Install/Test/etc/constraint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..921f167e82432e0ce4a17c484f7b4aa30e2a9b8d
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/etc/constraint.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<constraint>
+    <assertAgreementTextPresent module="Magento_Install">
+        <severity>low</severity>
+    </assertAgreementTextPresent>
+    <assertSuccessDbConnection module="Magento_Install">
+        <severity>low</severity>
+    </assertSuccessDbConnection>
+    <assertSuccessfulReadinessCheck module="Magento_Install">
+        <severity>low</severity>
+    </assertSuccessfulReadinessCheck>
+    <assertSuccessInstall module="Magento_Install">
+        <severity>low</severity>
+    </assertSuccessInstall>
+    <assertKeyCreated module="Magento_Install">
+        <severity>low</severity>
+    </assertKeyCreated>
+    <assertLanguageSelected module="Magento_Install">
+        <severity>low</severity>
+    </assertLanguageSelected>
+    <assertCurrencySelected module="Magento_Install">
+        <severity>low</severity>
+    </assertCurrencySelected>
+    <assertRewritesEnabled module="Magento_Install">
+        <severity>low</severity>
+    </assertRewritesEnabled>
+    <assertSecureUrlEnabled module="Magento_Install">
+        <severity>low</severity>
+    </assertSecureUrlEnabled>
+</constraint>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/etc/fixture.xml b/dev/tests/functional/tests/app/Magento/Install/Test/etc/fixture.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c5c091aad3d47305937ab785117e74916c18141b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/etc/fixture.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+
+<fixture>
+    <install module="Magento_Install">
+        <type>virtual</type>
+        <entity_type>install</entity_type>
+        <fields>
+            <dbHost>
+                <attribute_code>dbHost</attribute_code>
+                <backend_type>virtual</backend_type>
+            </dbHost>
+            <dbUser>
+                <attribute_code>dbUser</attribute_code>
+                <backend_type>virtual</backend_type>
+            </dbUser>
+            <dbPassword>
+                <attribute_code>dbPassword</attribute_code>
+                <backend_type>virtual</backend_type>
+            </dbPassword>
+            <dbname>
+                <attribute_code>dbname</attribute_code>
+                <backend_type>virtual</backend_type>
+            </dbname>
+            <web>
+                <attribute_code>web</attribute_code>
+                <backend_type>virtual</backend_type>
+            </web>
+        </fields>
+    </install>
+</fixture>
diff --git a/dev/tests/functional/tests/app/Magento/Install/Test/etc/page.xml b/dev/tests/functional/tests/app/Magento/Install/Test/etc/page.xml
new file mode 100644
index 0000000000000000000000000000000000000000..523ecd7d0672c81742917b4c4c78c102276db6f4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Install/Test/etc/page.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<page module="Magento_Install">
+    <install>
+        <mca>setup/</mca>
+        <class>Magento\Install\Test\Page\Install</class>
+    </install>
+</page>
diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Page/Adminhtml/SearchIndex.xml b/dev/tests/functional/tests/app/Magento/Reports/Test/Page/Adminhtml/SearchIndex.xml
index a8287d2ce082ba5ff51e7afb3a30e52f1e921c18..bbc913577f0f87c00ca91d7318ce15a3d0809e39 100644
--- a/dev/tests/functional/tests/app/Magento/Reports/Test/Page/Adminhtml/SearchIndex.xml
+++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Page/Adminhtml/SearchIndex.xml
@@ -4,7 +4,7 @@
  * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  */
 -->
-<page mca="reports/index/search" module="Magento_Reports">
+<page mca="search/term/report/" module="Magento_Reports">
     <blocks>
         <searchGrid>
             <class>Magento\Reports\Test\Block\Adminhtml\SearchTermsGrid</class>
diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php
index a1701cccd3a60d094527d8ffd3ac6b55bce955ea..dca52650288cc7fc6d00fba8e2c721df6d16fca6 100644
--- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SearchTermsReportEntityTest.php
@@ -72,7 +72,6 @@ class SearchTermsReportEntityTest extends Injectable
      */
     public function test($product, $countProducts, $countSearch)
     {
-        $this->markTestIncomplete('MAGETWO-30246');
         // Preconditions
         $productName = $this->createProducts($product, $countProducts);
 
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
index 6effc32b6bfd9d4a0a7616dcf35a5429bfe9819f..17773f76ef7bce33e6e51a1de7326a9d9fb057ad 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/TestCase/StoreTest.php
@@ -26,7 +26,7 @@ class StoreTest extends Functional
     public function testCreateNewLocalizedStoreView()
     {
         $objectManager = Factory::getObjectManager();
-        $storeFixture = $objectManager->create('\Magento\Store\Test\Fixture\Store', ['dataSet' => 'german']);
+        $storeFixture = $objectManager->create('Magento\Store\Test\Fixture\Store', ['dataSet' => 'german']);
 
         $storeListPage = Factory::getPageFactory()->getAdminSystemStore();
         $storeListPage->open();
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AbstractAssertTaxWithCrossBorderApplying.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AbstractAssertTaxWithCrossBorderApplying.php
index 0dc49a4adda17fd50ff6466b118e2a72246d8517..8bb7c9f9fdf0a7bcc6a0716a7d82e3209b0bedf5 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AbstractAssertTaxWithCrossBorderApplying.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AbstractAssertTaxWithCrossBorderApplying.php
@@ -179,7 +179,7 @@ abstract class AbstractAssertTaxWithCrossBorderApplying extends AbstractConstrai
     protected function loginCustomer($customer)
     {
         $this->objectManager->create(
-            '\Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep',
+            'Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep',
             ['customer' => $customer]
         )->run();
     }
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxRuleTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxRuleTest.php
index a3673f47e29a83f08cf5666adb50ef8cb71ced21..8f6c77c43c62ae4de32f25730078a6fdbce14cbe 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxRuleTest.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/TaxRuleTest.php
@@ -27,7 +27,7 @@ class TaxRuleTest extends Functional
     {
         //Data
         $objectManager = Factory::getObjectManager();
-        $fixture = $objectManager->create('\Magento\Tax\Test\Fixture\TaxRule', ['dataSet' => 'us_ca_ny_rule']);
+        $fixture = $objectManager->create('Magento\Tax\Test\Fixture\TaxRule', ['dataSet' => 'us_ca_ny_rule']);
         //Pages
         $taxGridPage = Factory::getPageFactory()->getTaxRuleIndex();
         $newTaxRulePage = Factory::getPageFactory()->getTaxRuleNew();
diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/BatCETests.php b/dev/tests/functional/testsuites/Mtf/TestSuite/BatCETests.php
deleted file mode 100644
index d5d16fc2cb8e37dc18aaefd17ccc4a5402ef747f..0000000000000000000000000000000000000000
--- a/dev/tests/functional/testsuites/Mtf/TestSuite/BatCETests.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * BAT CE
- *
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-
-namespace Mtf\TestSuite;
-
-class BatCETests
-{
-    public static function suite()
-    {
-        $suite = new TestSuite('BAT CE');
-
-        // Product
-        $suite->addTestSuite('Magento\Bundle\Test\TestCase\BundleFixedTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CreateTest');
-        $suite->addTestSuite('Magento\ConfigurableProduct\Test\TestCase\CreateConfigurableTest');
-        $suite->addTestSuite('Magento\ConfigurableProduct\Test\TestCase\CreateWithAttributeTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CreateSimpleWithCustomOptionsAndCategoryTest');
-
-        // Category
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Category\CreateTest');
-
-        // Stores
-        $suite->addTestSuite('Magento\Store\Test\TestCase\StoreTest');
-
-        return $suite;
-    }
-}
diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php b/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php
deleted file mode 100755
index a02b42d41eaf63ee5f53bda5c685f91b321567fe..0000000000000000000000000000000000000000
--- a/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * End-to-end scenarios without 3-rd party solutions for CE
- *
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-
-namespace Mtf\TestSuite;
-
-class EndToEndCETests
-{
-    public static function suite()
-    {
-        $suite = new TestSuite('End-to-end Scenarios without 3-rd Party Solutions for CE');
-
-        // Products
-        // Simple
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CreateProductTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\EditSimpleProductTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CreateSimpleWithCategoryTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\UnassignCategoryTest');
-        // Grouped
-        $suite->addTestSuite('Magento\GroupedProduct\Test\TestCase\CreateGroupedTest');
-        // Virtual
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CreateVirtualTest');
-        // Configurable
-        $suite->addTestSuite('Magento\ConfigurableProduct\Test\TestCase\EditConfigurableTest');
-        // Downloadable
-        $suite->addTestSuite('Magento\Downloadable\Test\TestCase\Create\LinksPurchasedSeparatelyTest');
-        // Bundle
-        $suite->addTestSuite('Magento\Bundle\Test\TestCase\BundleDynamicTest');
-        $suite->addTestSuite('Magento\Bundle\Test\TestCase\EditBundleTest');
-
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\UpsellTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\CrosssellTest');
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Product\RelatedProductTest');
-
-        // Product search
-        $suite->addTestSuite('Magento\CatalogSearch\Test\TestCase\AdvancedSearchTest');
-
-        // Url rewrites
-        $suite->addTestSuite('Magento\Urlrewrite\Test\TestCase\ProductTest');
-        $suite->addTestSuite('Magento\Urlrewrite\Test\TestCase\CategoryTest');
-
-        // Customer
-        $suite->addTestSuite('Magento\Customer\Test\TestCase\BackendCustomerCreateTest');
-        $suite->addTestSuite('Magento\Customer\Test\TestCase\CreateOnFrontendTest');
-
-        // Review
-        $suite->addTestSuite('Magento\Review\Test\TestCase\ReviewTest');
-
-        // Tax
-        $suite->addTestSuite('Magento\Tax\Test\TestCase\TaxRuleTest');
-
-        // Assign products to a category
-        $suite->addTestSuite('Magento\Catalog\Test\TestCase\Category\AssignProductTest');
-
-        return $suite;
-    }
-}
diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/bat_ce.xml b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/bat_ce.xml
new file mode 100644
index 0000000000000000000000000000000000000000..78345d2193aced1262f65a08c81cf78aac6b581e
--- /dev/null
+++ b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/bat_ce.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../vendor/magento/mtf/Mtf/TestRunner/etc/testRunner.xsd">
+    <rule scope="testsuite">
+        <allow>
+            <!--Products-->
+            <class value="Magento\Bundle\Test\TestCase\BundleFixedTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\CreateTest" />
+            <class value="Magento\ConfigurableProduct\Test\TestCase\CreateConfigurableTest" />
+            <class value="Magento\ConfigurableProduct\Test\TestCase\CreateWithAttributeTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\CreateSimpleWithCustomOptionsAndCategoryTest" />
+            <!--Category-->
+            <class value="Magento\Catalog\Test\TestCase\Category\CreateTest" />
+            <!--Stores-->
+            <class value="Magento\Store\Test\TestCase\StoreTest" />
+            <!--Quick Search-->
+            <class value="Magento\CatalogSearch\Test\TestCase\SearchEntityResultsTest" />
+        </allow>
+    </rule>
+    <rule scope="variation">
+        <allow>
+            <tag group="bamboo_plan" value="BAT" />
+        </allow>
+    </rule>
+</config>
diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/end_to_end_ce.xml b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/end_to_end_ce.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bd0624be9d69e32e6b9141dd63eddc713da92f9b
--- /dev/null
+++ b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests/end_to_end_ce.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../vendor/magento/mtf/Mtf/TestRunner/etc/testRunner.xsd">
+    <rule scope="testsuite">
+        <allow>
+            <!--Product search-->
+            <class value="Magento\CatalogSearch\Test\TestCase\AdvancedSearchEntityTest" />
+            <!--Products-->
+            <!--Simple-->
+            <class value="Magento\Catalog\Test\TestCase\Product\CreateProductTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\EditSimpleProductTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\CreateSimpleWithCategoryTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\UnassignCategoryTest" />
+            <!--Grouped-->
+            <class value="Magento\GroupedProduct\Test\TestCase\CreateGroupedTest" />
+            <!--Virtual-->
+            <class value="Magento\Catalog\Test\TestCase\Product\CreateVirtualTest" />
+            <!--Configurable-->
+            <class value="Magento\ConfigurableProduct\Test\TestCase\EditConfigurableTest" />
+            <!--Downloadable-->
+            <class value="Magento\Downloadable\Test\TestCase\Create\LinksPurchasedSeparatelyTest" />
+            <!--Bundle-->
+            <class value="Magento\Bundle\Test\TestCase\BundleDynamicTest" />
+            <class value="Magento\Bundle\Test\TestCase\EditBundleTest" />
+            <!--Related Products-->
+            <class value="Magento\Catalog\Test\TestCase\Product\UpsellTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\CrosssellTest" />
+            <class value="Magento\Catalog\Test\TestCase\Product\RelatedProductTest" />
+            <!--Url rewrites-->
+            <class value="Magento\UrlRewrite\Test\TestCase\ProductTest" />
+            <class value="Magento\UrlRewrite\Test\TestCase\CategoryTest" />
+            <!--Customer-->
+            <class value="Magento\Customer\Test\TestCase\BackendCustomerCreateTest" />
+            <class value="Magento\Customer\Test\TestCase\CreateOnFrontendTest" />
+            <!--Review-->
+            <class value="Magento\Review\Test\TestCase\ReviewTest" />
+            <!--Tax-->
+            <class value="Magento\Tax\Test\TestCase\TaxRuleTest" />
+            <!--Assign products to a category-->
+            <class value="Magento\Catalog\Test\TestCase\Category\AssignProductTest" />
+        </allow>
+    </rule>
+    <rule scope="variation">
+        <allow>
+            <tag group="bamboo_plan" value="end_to_end" />
+        </allow>
+    </rule>
+</config>
diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php
index 17caa1db0b137c8a9cabff91770ef28f2485b4e5..5ecbb875d993109d81f26d62c655ff39d432961d 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/Application.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php
@@ -272,10 +272,10 @@ class Application
         $objectManager->removeSharedInstance('Magento\Framework\Filesystem');
         $objectManager->addSharedInstance($filesystem, 'Magento\Framework\Filesystem');
 
-        /** @var \Magento\Framework\Logger $logger */
+        /** @var \Psr\Log\LoggerInterface $logger */
         $logger = $objectManager->get('Magento\TestFramework\ErrorLog\Logger');
-        $objectManager->removeSharedInstance('Magento\Framework\Logger');
-        $objectManager->addSharedInstance($logger, 'Magento\Framework\Logger');
+        $objectManager->removeSharedInstance('Psr\Log\LoggerInterface');
+        $objectManager->addSharedInstance($logger, 'Psr\Log\LoggerInterface');
 
         Helper\Bootstrap::setObjectManager($objectManager);
 
diff --git a/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Listener.php b/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Listener.php
index a74645c54aef3ab4863c5fbada46526ff7076872..e86373e49f13209e85d08692877f753bf4de87c6 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Listener.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Listener.php
@@ -72,7 +72,7 @@ class Listener implements \PHPUnit_Framework_TestListener
      */
     public function startTest(\PHPUnit_Framework_Test $test)
     {
-        $this->logger = Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Logger');
+        $this->logger = Helper\Bootstrap::getObjectManager()->get('Magento\TestFramework\ErrorLog\Logger');
         $this->logger->clearMessages();
     }
 
diff --git a/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Logger.php b/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Logger.php
index c97c2565cbabd5e071b620827cf514d61507925d..d548626cee8f89510417520553da95ba8c0062e7 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Logger.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/ErrorLog/Logger.php
@@ -4,7 +4,7 @@
  */
 namespace Magento\TestFramework\ErrorLog;
 
-class Logger extends \Magento\Framework\Logger
+class Logger extends \Magento\Framework\Logger\Monolog
 {
     /** @var array */
     protected $messages = [];
@@ -18,14 +18,10 @@ class Logger extends \Magento\Framework\Logger
      */
     protected $minimumErrorLevel;
 
-    /**
-     * @param \Magento\Framework\Filesystem $filesystem
-     * @param string $defaultFile
-     */
-    public function __construct(\Magento\Framework\Filesystem $filesystem, $defaultFile = '')
+    public function __construct()
     {
-        parent::__construct($filesystem, $defaultFile);
         $this->minimumErrorLevel = defined('TESTS_ERROR_LOG_LISTENER_LEVEL') ? TESTS_ERROR_LOG_LISTENER_LEVEL : -1;
+        parent::__construct('integration-test');
     }
 
     /**
@@ -43,21 +39,4 @@ class Logger extends \Magento\Framework\Logger
     {
         return $this->messages;
     }
-
-    /**
-     * @param string $message
-     * @param int $level
-     * @param string $loggerKey
-     */
-    public function log($message, $level = \Zend_Log::DEBUG, $loggerKey = \Magento\Framework\Logger::LOGGER_SYSTEM)
-    {
-        if ($level <= $this->minimumErrorLevel) {
-            $this->messages[] = [
-                'logger' => $loggerKey,
-                'level' => $level,
-                'message' => $message,
-            ];
-        }
-        parent::log($message, $level, $loggerKey);
-    }
 }
diff --git a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractConfigFiles.php b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractConfigFiles.php
index 9a51c6c64c063a8113ea490105deecc0750f98d0..9706eb58e3354c69e5c8f19afc7cc5d7b9de3735 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractConfigFiles.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractConfigFiles.php
@@ -133,7 +133,7 @@ abstract class AbstractConfigFiles extends \PHPUnit_Framework_TestCase
         $directory = $objectManager->get('Magento\Framework\Filesystem')
             ->getDirectoryRead(DirectoryList::MODULES);
 
-        return $objectManager->get('\Magento\Framework\Config\FileIteratorFactory')
+        return $objectManager->get('Magento\Framework\Config\FileIteratorFactory')
             ->create($directory, $directory->search($this->_getConfigFilePathGlob()));
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/GridTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/GridTest.php
index 2accd8b009eba2c53e8d4ce9eddbe28ec1a61f3e..76152ca7b91c29573c2612dccec38f5de48846fb 100644
--- a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/GridTest.php
+++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/GridTest.php
@@ -106,7 +106,7 @@ class GridTest extends \PHPUnit_Framework_TestCase
                     'Magento\Framework\View\Element\Template\Context',
                     [
                         'filesystem' => $objectManager->create(
-                            '\Magento\Framework\Filesystem',
+                            'Magento\Framework\Filesystem',
                             ['directoryList' => $directoryList]
                         )
                     ]
diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/AuthTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/AuthTest.php
index c0d6f56d0a91d3596bf252670450bb7a6b27a7cb..9583306450bf923d3b8fbdab930429cc15ad58d2 100644
--- a/dev/tests/integration/testsuite/Magento/Backend/Model/AuthTest.php
+++ b/dev/tests/integration/testsuite/Magento/Backend/Model/AuthTest.php
@@ -80,7 +80,7 @@ class AuthTest extends \PHPUnit_Framework_TestCase
             \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD
         );
         $this->assertNotEmpty($this->_model->getAuthStorage()->getData());
-        $cookie = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('\Magento\Framework\Stdlib\Cookie');
+        $cookie = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Stdlib\Cookie');
         $cookie->set($this->_model->getAuthStorage()->getName(), 'session_id');
         $this->_model->logout();
         $this->assertEmpty($this->_model->getAuthStorage()->getData());
diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/SessionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/SessionTest.php
index 1b8db05de4677937750b61717ba7d088e9a762d9..8c49a3d858962f4dac06ea1ec7fd59e4b693f876 100644
--- a/dev/tests/integration/testsuite/Magento/Backend/Model/SessionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Backend/Model/SessionTest.php
@@ -16,7 +16,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase
         if (array_key_exists('adminhtml', $_SESSION)) {
             unset($_SESSION['adminhtml']);
         }
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
             'Magento\Backend\Model\Session',
             [$logger]
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/NewTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/NewTest.php
index c12895d67ecc6ec8faed0455264f885ea3f655c3..9cc35b8ea03aee464ef9048b41847cc0c263c2ef 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/NewTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/NewTest.php
@@ -22,7 +22,7 @@ class NewTest extends \PHPUnit_Framework_TestCase
          * @var \Magento\Customer\Api\GroupManagementInterface $groupManagement
          */
         $groupManagement = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Customer\Api\GroupManagementInterface');
+            ->get('Magento\Customer\Api\GroupManagementInterface');
         $notLoggedInId = $groupManagement->getNotLoggedInGroup()->getId();
 
         \Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea(\Magento\Framework\App\Area::AREA_FRONTEND);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php
index 410c81020ce82cc6df11f1698b9152c6977a7e7e..948a96da436a9f1f755baf7d1a40d5e80707bff0 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php
@@ -22,7 +22,7 @@ class FlatTest extends \PHPUnit_Framework_TestCase
             'Magento\Catalog\Helper\Product\Flat\Indexer'
         );
         $this->_state = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\Indexer\Product\Flat\State'
+            'Magento\Catalog\Model\Indexer\Product\Flat\State'
         );
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/FullTest.php
index c0e46ec17ba07dcc8d4322a73485808e26cd9218..73e8cfc246098baef4b16b509b085b8dffe969cf 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/FullTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/FullTest.php
@@ -38,11 +38,11 @@ class FullTest extends \PHPUnit_Framework_TestCase
         $this->_processor->reindexAll();
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowTest.php
index cf8a2af24f0f57dbe4cd918399efae276213e268..9b2f7a5ff760e4833015fd1cf70dc11ecadbb8d7 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowTest.php
@@ -33,11 +33,11 @@ class RowTest extends \PHPUnit_Framework_TestCase
         $product->save();
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowsTest.php
index ebddf8185232d9935019050f7c18d86458027a2b..d6e7a0c6e247a84db9c6daea77a75478e27b2dd7 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowsTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Eav/Action/RowsTest.php
@@ -42,11 +42,11 @@ class RowsTest extends \PHPUnit_Framework_TestCase
         );
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/FullTest.php
index 91b50ef48503d9468716175f14e953ec9c99b38e..679611aa5ec2ee56c650ed30573b7326cf43574e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/FullTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/FullTest.php
@@ -31,10 +31,10 @@ class FullTest extends \PHPUnit_Framework_TestCase
         $this->_processor->reindexAll();
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowTest.php
index 6fc0d65ccb008c32ac1afeb94a1ab996b845c98c..05e8cc116fb64b8a856d56bd96c71314cadda01e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowTest.php
@@ -37,10 +37,10 @@ class RowTest extends \PHPUnit_Framework_TestCase
     public function testProductUpdate()
     {
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $this->_processor->getIndexer()->setScheduled(false);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowsTest.php
index 85a40e054b255178c210767b94d1202e12285c77..949334c2aabba312a5f779da8c6f5903c4233f92 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowsTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Action/RowsTest.php
@@ -41,10 +41,10 @@ class RowsTest extends \PHPUnit_Framework_TestCase
         $this->_processor->reindexList([$this->_product->getId()]);
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(9);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/DataProvider/PriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/DataProvider/PriceTest.php
index c98c982ae7d3313943f48c44595fe0df928a6306..4d0272067cc3b42475b641d41512d8097c2a96e1 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/DataProvider/PriceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/DataProvider/PriceTest.php
@@ -24,7 +24,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         );
         $category->load(4);
         $layer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Catalog\Model\Layer\Category');
+            ->get('Magento\Catalog\Model\Layer\Category');
         $layer->setCurrentCategory($category);
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
             ->create('Magento\Catalog\Model\Layer\Filter\DataProvider\Price', ['layer' => $layer]);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/PriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/PriceTest.php
index e1ff64c14b70198cdd71e00a8ccbde10d01410b9..5161866043959227fb72f7e14005fcc71e880f7d 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/PriceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/PriceTest.php
@@ -28,12 +28,12 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         );
         $category->load(4);
         $layer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Catalog\Model\Layer\Category');
+            ->get('Magento\Catalog\Model\Layer\Category');
         $layer->setCurrentCategory($category);
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
             ->create('Magento\Catalog\Model\Layer\Filter\Price', ['layer' => $layer]);
         $this->groupManagement = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Customer\Api\GroupManagementInterface');
+            ->get('Magento\Customer\Api\GroupManagementInterface');
     }
 
     public function testApplyNothing()
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
index cb7cc49ea3c16c36b913abd62e69b02b29a88aa0..47a3fca574925c2993773583c785dd973659aac4 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
@@ -31,7 +31,7 @@ class AbstractTypeTest extends \PHPUnit_Framework_TestCase
         $fileStorageDb = $this->getMock('Magento\Core\Helper\File\Storage\Database', [], [], '', false);
         $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
         $registry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         $this->_model = $this->getMockForAbstractClass(
             'Magento\Catalog\Model\Product\Type\AbstractType',
             [
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
index f95746c869f4a393cd17321205ffc11620c09548..06ee8df098b93ff260e7f6c3b85ba62d5ed6229a 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
@@ -28,7 +28,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     public function testAddLinkAttributeToFilterWithResults()
     {
         $om = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $link = $om->get('\Magento\Catalog\Model\Product\Link')->useCrossSellLinks();
+        $link = $om->get('Magento\Catalog\Model\Product\Link')->useCrossSellLinks();
         $this->collection->setLinkModel($link);
         $this->collection->addLinkAttributeToFilter('position', ['from' => 0, 'to' => 2]);
         $product = $om->get('Magento\Catalog\Model\Product')->load(2);
@@ -47,7 +47,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     public function testAddLinkAttributeToFilterNoResults()
     {
         $om = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $link = $om->get('\Magento\Catalog\Model\Product\Link')->useCrossSellLinks();
+        $link = $om->get('Magento\Catalog\Model\Product\Link')->useCrossSellLinks();
         $this->collection->setLinkModel($link);
         $this->collection->addLinkAttributeToFilter('position', ['from' => 2, 'to' => 3]);
         $product = $om->get('Magento\Catalog\Model\Product')->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/OptionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/OptionTest.php
index 38116e3a2ab0ae3c5eb9163bfeeeeb91ae73732a..c0b5b823179667f0ab7666a9a4877a078a68ac8e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/OptionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Resource/Product/OptionTest.php
@@ -101,7 +101,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
 
         $title = $options[0]['values'][0]['title'];
         $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Model\Product'
+            'Magento\Catalog\Model\Product'
         );
         $product->load($productId);
         $product->setStoreIds([$storeId]);
@@ -152,7 +152,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
         $price = $options[0]['values'][0]['price'];
         $priceType = $options[0]['values'][0]['price_type'];
         $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Model\Product'
+            'Magento\Catalog\Model\Product'
         );
         $product->load($productId);
         $product->setStoreIds([$storeId]);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php
index 7b1ac48421d9f50fb4dee713cef1acb8f4540150..bdd5d6924e97b4e6b52af44901edcd19c299a42c 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php
@@ -7,10 +7,10 @@
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 
 /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
-$attributeSet = $objectManager->create('\Magento\Eav\Model\Entity\Attribute\Set');
+$attributeSet = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Set');
 
 $entityType = $objectManager->create('Magento\Eav\Model\Entity\Type')->loadByCode('catalog_product');
-$defaultSetId = $objectManager->create('\Magento\Catalog\Model\Product')->getDefaultAttributeSetid();
+$defaultSetId = $objectManager->create('Magento\Catalog\Model\Product')->getDefaultAttributeSetid();
 
 $data = [
     'attribute_set_name' => 'attribute_set_with_media_attribute',
@@ -37,6 +37,6 @@ $attributeData = [
 ];
 
 /** @var \Magento\Catalog\Model\Entity\Attribute $attribute */
-$attribute = $objectManager->create('\Magento\Catalog\Model\Entity\Attribute');
+$attribute = $objectManager->create('Magento\Catalog\Model\Entity\Attribute');
 $attribute->setData($attributeData);
 $attribute->save();
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php
index 645c78057865fd93f8e60478f783314870a7d321..117e9c4d0dace7107330a8fca8d16bdcfe31cc9d 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php
@@ -11,7 +11,7 @@ $entityType = $objectManager->create('Magento\Eav\Model\Entity\Type')->loadByCod
 // remove attribute
 
 /** @var \Magento\Catalog\Model\Resource\Product\Attribute\Collection $attributeCollection */
-$attributeCollection = $objectManager->create('\Magento\Catalog\Model\Resource\Product\Attribute\Collection');
+$attributeCollection = $objectManager->create('Magento\Catalog\Model\Resource\Product\Attribute\Collection');
 $attributeCollection->setFrontendInputTypeFilter('media_image');
 $attributeCollection->setCodeFilter('funny_image');
 $attributeCollection->setEntityTypeFilter($entityType->getId());
@@ -23,7 +23,7 @@ $attribute->delete();
 // remove attribute set
 
 /** @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection $attributeSetCollection */
-$attributeSetCollection = $objectManager->create('\Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection');
+$attributeSetCollection = $objectManager->create('Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection');
 $attributeSetCollection->addFilter('attribute_set_name', 'attribute_set_with_media_attribute');
 $attributeSetCollection->addFilter('entity_type_id', $entityType->getId());
 $attributeSetCollection->setOrder('attribute_set_id'); // descending is default value
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group.php
index 28966589455c87fdca93df327a7e5c194b8df6f3..7a94a52af2d06db391162f3be7048438f4263655 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group.php
@@ -4,7 +4,7 @@
  */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 /** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */
-$attributeGroup = $objectManager->create('\Magento\Eav\Model\Entity\Attribute\Group');
+$attributeGroup = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Group');
 $entityTypeId = $objectManager->create('Magento\Eav\Model\Entity\Type')->loadByCode('catalog_product')->getId();
 $attributeGroup->setData([
     'attribute_group_name' => 'empty_attribute_group',
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group_rollback.php
index 2fd90f66832e3def02413727d3b8f4b8e3d1f8c7..64a41828d2d27f543dac8a8418d8b6de373ce058 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/empty_attribute_group_rollback.php
@@ -4,13 +4,13 @@
  */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 /** @var \Magento\Eav\Model\Entity\Attribute\Group $attributeSet */
-$attributeGroup = $objectManager->create('\Magento\Eav\Model\Entity\Attribute\Group')
+$attributeGroup = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Group')
     ->load('empty_attribute_group', 'attribute_group_name');
 if ($attributeGroup->getId()) {
     $attributeGroup->delete();
 }
 
-$attributeGroupUpdated = $objectManager->create('\Magento\Eav\Model\Entity\Attribute\Group')
+$attributeGroupUpdated = $objectManager->create('Magento\Eav\Model\Entity\Attribute\Group')
     ->load('empty_attribute_group_updated', 'attribute_group_name');
 if ($attributeGroupUpdated->getId()) {
     $attributeGroupUpdated->delete();
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php
index f4143ddb9cdc23fadba85c1554da9fe90957cbdb..2c475a9f3e57f1852cab72c46af88a44d7512769 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php
@@ -50,9 +50,9 @@ class ManagestockTest extends \PHPUnit_Framework_TestCase
             ->method('rebuild');
 
         $manageStock = new Managestock(
-            Bootstrap::getObjectManager()->get('\Magento\Framework\Model\Context'),
-            Bootstrap::getObjectManager()->get('\Magento\Framework\Registry'),
-            Bootstrap::getObjectManager()->get('\Magento\Framework\App\Config\ScopeConfigInterface'),
+            Bootstrap::getObjectManager()->get('Magento\Framework\Model\Context'),
+            Bootstrap::getObjectManager()->get('Magento\Framework\Registry'),
+            Bootstrap::getObjectManager()->get('Magento\Framework\App\Config\ScopeConfigInterface'),
             $stockManagement,
             Bootstrap::getObjectManager()->get('Magento\CatalogInventory\Model\Indexer\Stock\Processor'),
             Bootstrap::getObjectManager()->get('Magento\Core\Model\Resource\Config')
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php
index d4fd95a045306371131a8fa2c14847a711022dbb..89cf2b837cf4a8973ae0aced19ccb120eac9e362 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/FullTest.php
@@ -31,11 +31,11 @@ class FullTest extends \PHPUnit_Framework_TestCase
         $this->_processor->reindexAll();
 
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         $category = $categoryFactory->create()->load(2);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowTest.php
index 026b38f891041cf4bb815a3c868c2a6a9ad72274..473cc73fee4d6c7409706f2043e8bea4f8763b7e 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowTest.php
@@ -27,16 +27,16 @@ class RowTest extends \PHPUnit_Framework_TestCase
     public function testProductUpdate()
     {
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         /** @var \Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder $stockItemBuilder */
         $stockItemBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder'
+            'Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder'
         );
 
         /** @var \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry */
@@ -45,7 +45,7 @@ class RowTest extends \PHPUnit_Framework_TestCase
         );
         /** @var \Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository */
         $stockItemRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\CatalogInventory\Api\StockItemRepositoryInterface'
+            'Magento\CatalogInventory\Api\StockItemRepositoryInterface'
         );
 
         $this->_processor->getIndexer()->setScheduled(false);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowsTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowsTest.php
index 2d018b6e00c657bd2eb15e67157b569f741e1a8c..402488cac91b714ef99fb7f9d8c3f2ca683c5395 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowsTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Indexer/Stock/Action/RowsTest.php
@@ -27,16 +27,16 @@ class RowsTest extends \PHPUnit_Framework_TestCase
     public function testProductUpdate()
     {
         $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Model\CategoryFactory'
+            'Magento\Catalog\Model\CategoryFactory'
         );
         /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
         $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Catalog\Block\Product\ListProduct'
+            'Magento\Catalog\Block\Product\ListProduct'
         );
 
         /** @var \Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder $stockRegistry */
         $stockItemBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder'
+            'Magento\CatalogInventory\Api\Data\StockItemInterfaceBuilder'
         );
 
         /** @var \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry */
@@ -45,12 +45,12 @@ class RowsTest extends \PHPUnit_Framework_TestCase
         );
         /** @var \Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository */
         $stockItemRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\CatalogInventory\Api\StockItemRepositoryInterface'
+            'Magento\CatalogInventory\Api\StockItemRepositoryInterface'
         );
 
         /** @var \Magento\CatalogInventory\Model\Resource\Stock\Item $stockItemResource */
         $stockItemResource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\CatalogInventory\Model\Resource\Stock\Item'
+            'Magento\CatalogInventory\Model\Resource\Stock\Item'
         );
 
         $stockItem = $stockRegistry->getStockItem(1, 1);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/Advanced/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/Advanced/ResultTest.php
index 7148428c9ac5b174c800ed792c38c134c8969413..f0e200b636270559be01bac431d474508a88217f 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/Advanced/ResultTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/Advanced/ResultTest.php
@@ -48,7 +48,7 @@ class ResultTest extends \PHPUnit_Framework_TestCase
         $category->setId(100500); // Any id - just for layer navigation
         /** @var \Magento\Catalog\Model\Layer\Resolver $resolver */
         $resolver = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Catalog\Model\Layer\Resolver');
+            ->get('Magento\Catalog\Model\Layer\Resolver');
         $resolver->get()->setCurrentCategory($category);
 
         $childBlock = $this->_layout->addBlock('Magento\Framework\View\Element\Text', 'search_result_list', 'block');
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Helper/DataTest.php
index ae968cbb819555950238a6375828c0cef1b9d2f9..00ab87d893695e65f7425ae0a78eeb7b28182e33 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Helper/DataTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Helper/DataTest.php
@@ -16,7 +16,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
         /** @var \Magento\TestFramework\ObjectManager  $objectManager */
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         /** @var \Magento\Framework\App\Request\Http $request */
-        $request = $objectManager->get('\Magento\Framework\App\RequestInterface');
+        $request = $objectManager->get('Magento\Framework\App\RequestInterface');
         $request->setParam('q', 'five <words> here <being> tested');
         $this->_helper = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\CatalogSearch\Helper\Data'
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Layer/Filter/PriceTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Layer/Filter/PriceTest.php
index 2537014e94b418b5388d5fb19f142309839c0bf3..4fbd3a84f093b21e040ebd6736b826b56c5326be 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Layer/Filter/PriceTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Layer/Filter/PriceTest.php
@@ -23,7 +23,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         );
         $category->load(4);
         $layer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->get('\Magento\Catalog\Model\Layer\Category');
+            ->get('Magento\Catalog\Model\Layer\Category');
         $layer->setCurrentCategory($category);
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
             ->create('Magento\CatalogSearch\Model\Layer\Filter\Price', ['layer' => $layer]);
diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Search/CatalogTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Search/CatalogTest.php
index b55a860c1f788ab68525a4d724d124d523dda3d0..0f0b6b748cc014c79aabf5998ea164b338824328 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Search/CatalogTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Search/CatalogTest.php
@@ -16,7 +16,7 @@ class CatalogTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->catalogSearch = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->create('\Magento\CatalogSearch\Model\Search\Catalog');
+            ->create('Magento\CatalogSearch\Model\Search\Catalog');
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php
index b97f1d0667c0bb66c79a521c5bb9a04ffa92361d..ec857c1bde0ad41df2009a297c1d77c5ec7ca63f 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php
@@ -43,7 +43,7 @@ class BillingTest extends \PHPUnit_Framework_TestCase
         $this->_customerRepository = $objectManager->create('Magento\Customer\Api\CustomerRepositoryInterface');
         $customer = $this->_customerRepository->getById(self::FIXTURE_CUSTOMER_ID);
 
-        $customerSession = $objectManager->get('\Magento\Customer\Model\Session');
+        $customerSession = $objectManager->get('Magento\Customer\Model\Session');
         $customerSession->setCustomerData($customer);
 
         $this->_addressRepository = $objectManager->get('Magento\Customer\Api\AddressRepositoryInterface');
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Controller/OnepageTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Controller/OnepageTest.php
index cde2a86b1051878650b5b2c3b2b63152d80ed014..228ed3b174f8c98dd85c19691a1f481d76c1c44e 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/Controller/OnepageTest.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/Controller/OnepageTest.php
@@ -56,7 +56,7 @@ class OnepageTest extends \Magento\TestFramework\TestCase\AbstractController
 
     public function testSaveOrderActionWithFormKey()
     {
-        $formKey = $this->_objectManager->get('\Magento\Framework\Data\Form\FormKey');
+        $formKey = $this->_objectManager->get('Magento\Framework\Data\Form\FormKey');
         $this->getRequest()->setParam('form_key', $formKey->getFormKey());
         $this->dispatch('checkout/onepage/saveOrder');
         $html = $this->getResponse()->getBody();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_saved_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_saved_rollback.php
index 72299fe0f47474366f34b5ba1db0370c3942c0b0..de7d649c73c233bee7db2cf25e3acb67ac2f3070 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_saved_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_address_saved_rollback.php
@@ -7,5 +7,5 @@
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_1', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved_rollback.php
index 3ab5c1e99b403d7c523867f25cd4dced0e3eca2c..1cd90ff860e2abbd19f261bf7883e55e96d99a6a 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved_rollback.php
@@ -7,5 +7,5 @@
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_1', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_payment_saved_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_payment_saved_rollback.php
index 86ddf3132a32b3e55d89cd2c8bf3549484ac9ab3..9e17789926a3f509c67e2db060f3633a35c62751 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_payment_saved_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_payment_saved_rollback.php
@@ -7,5 +7,5 @@
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_1_with_payment', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_simple_product_saved_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_simple_product_saved_rollback.php
index 89f9c1904bc743b3b892a66cf8dc4db2b17d2c5b..b10d221b9c7e799dae4a3ed894a9da5800890ca1 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_simple_product_saved_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_simple_product_saved_rollback.php
@@ -7,5 +7,5 @@
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_with_simple_product_without_address', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_and_address_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_and_address_rollback.php
index 23b3ce94d602a0ef772dbee44e3e301035a5e7a0..4a8529c87fb9a41af9448d3af46002bb21fdf0ad 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_and_address_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_and_address_rollback.php
@@ -6,5 +6,5 @@
  */
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_with_virtual_product', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved_rollback.php
index 4b569f046133f9acdfad33e118ca7fe5d1d7dc35..95e6b8af75f29ee3c46e00be0c953df9dfd89be2 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_virtual_product_saved_rollback.php
@@ -7,5 +7,5 @@
 
 /** @var $objectManager \Magento\TestFramework\ObjectManager */
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-$quote = $objectManager->create('\Magento\Sales\Model\Quote');
+$quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_with_virtual_product_without_address', 'reserved_order_id')->delete();
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php
index 4f7d447b7b0abdde9db34230770bcba9fc272d4c..ec1aeb73a48a05d8de1890026f8fbb14f6dde9a2 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php
@@ -34,7 +34,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase
         $this->repository = $this->_objectManager->create('Magento\Customer\Api\AddressRepositoryInterface');
         $this->_addressBuilder = $this->_objectManager->create('Magento\Customer\Api\Data\AddressDataBuilder');
 
-        $builder = $this->_objectManager->create('\Magento\Customer\Api\Data\RegionDataBuilder');
+        $builder = $this->_objectManager->create('Magento\Customer\Api\Data\RegionDataBuilder');
         $region = $builder
             ->setRegionCode('AL')
             ->setRegion('Alabama')
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Address/EditTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Address/EditTest.php
index 9ce8d04c04a8c70b53ba787a74cfca2c763c140f..5f75bfa8f19552cd205d7e814dbeaff607593662 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Block/Address/EditTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Address/EditTest.php
@@ -25,7 +25,7 @@ class EditTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 
-        $this->_customerSession = $objectManager->get('\Magento\Customer\Model\Session');
+        $this->_customerSession = $objectManager->get('Magento\Customer\Model\Session');
         $this->_customerSession->setCustomerId(1);
 
         $this->_context = $objectManager->get('Magento\Backend\Block\Template\Context');
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
index 910039c9d8b17cc4867de7f8eaf29b0dd952df87..c66adba030c3cc9448f3edcbf4d19c924c093c4e 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
@@ -167,7 +167,7 @@ class AccountTest extends \PHPUnit_Framework_TestCase
     public function testNewCustomer()
     {
         /** @var \Magento\Customer\Api\Data\CustomerDataBuilder $customerBuilder */
-        $customerBuilder = $this->objectManager->get('\Magento\Customer\Api\Data\CustomerDataBuilder');
+        $customerBuilder = $this->objectManager->get('Magento\Customer\Api\Data\CustomerDataBuilder');
         $customerData = $this->dataObjectProcessor
             ->buildOutputDataArray($customerBuilder->create(), '\Magento\Customer\Api\Data\CustomerInterface');
         $this->backendSession->setCustomerData(
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfoTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfoTest.php
index 8f771f5dfd6cd867840e22c5f900e7e458ca803c..e67b270c5698dcb99f0578edbc7dda2533bf7526 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfoTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/View/PersonalInfoTest.php
@@ -65,7 +65,7 @@ class PersonalInfoTest extends \PHPUnit_Framework_TestCase
         $this->_dataObjectProcessor = $this->_objectManager->get('Magento\Framework\Reflection\DataObjectProcessor');
 
         $this->_groupRepository = $this->_objectManager->get('Magento\Customer\Api\GroupRepositoryInterface');
-        $this->dateTime = $this->_objectManager->get('\Magento\Framework\Stdlib\DateTime');
+        $this->dateTime = $this->_objectManager->get('Magento\Framework\Stdlib\DateTime');
 
         $this->_block = $this->_objectManager->get(
             'Magento\Framework\View\LayoutInterface'
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Group/EditTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Group/EditTest.php
index f0ab8217eb8812a2bdcfe7849c5230d55d7fe27a..9fe6f349d506734e09c6f17dc5e899c153dcd106 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Group/EditTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Group/EditTest.php
@@ -80,7 +80,7 @@ class EditTest extends AbstractController
      */
     public function testDeleteButtonExistInCustomGroup()
     {
-        $builder = Bootstrap::getObjectManager()->create('\Magento\Framework\Api\FilterBuilder');
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
         /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteria */
         $searchCriteria = Bootstrap::getObjectManager()
             ->create('Magento\Framework\Api\SearchCriteriaBuilder')
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php
index 75f463af75981787eca161678dfe29dc4a94d174..2ff68a63b48dd14027592f5da89d3e48688da35b 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php
@@ -14,7 +14,7 @@ class AddressTest extends \Magento\TestFramework\TestCase\AbstractController
     protected function setUp()
     {
         parent::setUp();
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         $session = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
             'Magento\Customer\Model\Session',
             [$logger]
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php
index 4bf13eed6fc348ace9c091014a9551dcf1b4a480..426b24433e22f59e5f62e1e44b233a10c06abfec 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Cart/Product/Composite/CartTest.php
@@ -18,7 +18,7 @@ class CartTest extends \Magento\Backend\Utility\Controller
     {
         parent::setUp();
         $this->quoteItemCollectionFactory = $this->_objectManager->get(
-            '\Magento\Sales\Model\Resource\Quote\Item\CollectionFactory'
+            'Magento\Sales\Model\Resource\Quote\Item\CollectionFactory'
         );
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/AddressRepositoryTest.php
index ebdd0e357273e185b948088241206a1e541b6852..113c9eb6d6924d1572b599bbfa8fb721cd348f69 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/AddressRepositoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/AddressRepositoryTest.php
@@ -35,7 +35,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase
         $this->repository = $this->_objectManager->create('Magento\Customer\Api\AddressRepositoryInterface');
         $this->_addressBuilder = $this->_objectManager->create('Magento\Customer\Api\Data\AddressDataBuilder');
 
-        $builder = $this->_objectManager->create('\Magento\Customer\Api\Data\RegionDataBuilder');
+        $builder = $this->_objectManager->create('Magento\Customer\Api\Data\RegionDataBuilder');
         $region = $builder
             ->setRegionCode('AL')
             ->setRegion('Alabama')
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/CustomerRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/CustomerRepositoryTest.php
index 103fe685bdebdc1b22047bd59bda52a7c9d597bd..24210493d4d8e1d2c2f25f2f0cf8b9fc3f874c80 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/CustomerRepositoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Resource/CustomerRepositoryTest.php
@@ -271,7 +271,7 @@ class CustomerRepositoryTest extends \PHPUnit_Framework_TestCase
 
     public function searchCustomersDataProvider()
     {
-        $builder = Bootstrap::getObjectManager()->create('\Magento\Framework\Api\FilterBuilder');
+        $builder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
         return [
             'Customer with specific email' => [
                 [$builder->setField('email')->setValue('customer@search.example.com')->create()],
@@ -321,14 +321,14 @@ class CustomerRepositoryTest extends \PHPUnit_Framework_TestCase
         $searchBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaDataBuilder');
 
         // Filter for 'firstname' like 'First'
-        $filterBuilder = $objectManager->create('\Magento\Framework\Api\FilterBuilder');
+        $filterBuilder = $objectManager->create('Magento\Framework\Api\FilterBuilder');
         $firstnameFilter = $filterBuilder->setField('firstname')
             ->setConditionType('like')
             ->setValue('First%')
             ->create();
         $searchBuilder->addFilter([$firstnameFilter]);
         // Search ascending order
-        $sortOrderBuilder = $objectManager->create('\Magento\Framework\Api\SortOrderBuilder');
+        $sortOrderBuilder = $objectManager->create('Magento\Framework\Api\SortOrderBuilder');
         $sortOrder = $sortOrderBuilder
             ->setField('lastname')
             ->setDirection(SearchCriteriaInterface::SORT_ASC)
diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer.php
index 5d196d0bb0868282e07b36309647ed987b3fa1e1..aa4af34c98fb6d7d254fbba5f3ea1b88e7892e2d 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer.php
@@ -5,7 +5,7 @@
 
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 /** @var $repository \Magento\Customer\Api\CustomerRepositoryInterface */
-$repository = $objectManager->create('\Magento\Customer\Api\CustomerRepositoryInterface');
+$repository = $objectManager->create('Magento\Customer\Api\CustomerRepositoryInterface');
 $customer = $objectManager->create('Magento\Customer\Model\Customer');
 
 /** @var Magento\Customer\Model\Customer $customer */
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php
index 65ed2f489ee247d63aff68366e5ec341587a23b4..e3db90f4ae5c348985082c722a23a946cf441f4d 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Data/Form/Element/DateTest.php
@@ -24,7 +24,7 @@ class DateTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         $this->_elementFactory = $objectManager->create('Magento\Framework\Data\Form\ElementFactory');
-        $this->_localeDate = $objectManager->get('\Magento\Framework\Stdlib\DateTime\Timezone');
+        $this->_localeDate = $objectManager->get('Magento\Framework\Stdlib\DateTime\Timezone');
     }
 
     /**
@@ -48,29 +48,29 @@ class DateTest extends \PHPUnit_Framework_TestCase
      */
     public function getValueDataProvider()
     {
-        $currentTime = time();
+        $testTimestamp = strtotime('2014-05-18 12:08:16');
         return [
             [
                 [
                     'date_format' => \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
                     'time_format' => \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
-                    'value' => $currentTime,
+                    'value' => $testTimestamp,
                 ],
-                date('m/j/y g:i A', $currentTime),
+                date('n/j/y g:i A', $testTimestamp),
             ],
             [
                 [
                     'time_format' => \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
-                    'value' => $currentTime,
+                    'value' => $testTimestamp,
                 ],
-                date('g:i A', $currentTime)
+                date('g:i A', $testTimestamp)
             ],
             [
                 [
                     'date_format' => \Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT,
-                    'value' => $currentTime,
+                    'value' => $testTimestamp,
                 ],
-                date('m/j/y', $currentTime)
+                date('n/j/y', $testTimestamp)
             ]
         ];
     }
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractTest.php b/dev/tests/integration/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractTest.php
index ecfd7fa158df532a4fb7d6d34262a894859ac69f..cbf2052f709b49c4df346a291afa07eb013a4c0b 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractTest.php
@@ -43,7 +43,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase
         $entityFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\Core\Model\EntityFactory'
         );
-        $logger = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Logger');
+        $logger = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Psr\Log\LoggerInterface');
 
         $this->_model = $this->getMockForAbstractClass(
             'Magento\Framework\Model\Resource\Db\Collection\AbstractCollection',
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Module/DataSetupTest.php b/dev/tests/integration/testsuite/Magento/Framework/Module/DataSetupTest.php
index 1186ce0262e347a10214e1da34bc36e1391e99c0..23adfd0278521b5b5ce97c6f010b0e15c2fdaa7c 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Module/DataSetupTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Module/DataSetupTest.php
@@ -23,7 +23,7 @@ class DataSetupTest extends \PHPUnit_Framework_TestCase
     {
         /* reset data version */
         \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            '\Magento\Framework\Module\ResourceInterface'
+            'Magento\Framework\Module\ResourceInterface'
         )->setDataVersion(
             'adminnotification_setup',
             false
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php
index c4fad76c42d8ebaf047b25072a8f4bf2389c4e1a..fa8fe5f9b6d1f4c0f2fea7245e93d566e4c4224d 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Module/Plugin/DbStatusValidatorTest.php
@@ -24,7 +24,7 @@ class DbStatusValidatorTest extends \Magento\TestFramework\TestCase\AbstractCont
         $moduleList = $objectManager->get('Magento\Framework\Module\ModuleListInterface');
 
         /** @var \Magento\Framework\Module\ResourceResolverInterface $resourceResolver */
-        $resourceResolver = $objectManager->get('\Magento\Framework\Module\ResourceResolverInterface');
+        $resourceResolver = $objectManager->get('Magento\Framework\Module\ResourceResolverInterface');
 
         // get first resource, we don't care which one it is.
         foreach ($moduleList->getNames() as $moduleName) {
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
index 394581ba4bd2fb28a42283738f72f7a8a378c439..0a3f75362d96b35d2883695d162d114eb52621f5 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
@@ -83,7 +83,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
     private function reindexAll()
     {
         /** @var \Magento\Indexer\Model\Indexer[] $indexerList */
-        $indexerList = $this->objectManager->get('\Magento\Indexer\Model\Indexer\CollectionFactory')
+        $indexerList = $this->objectManager->get('Magento\Indexer\Model\Indexer\CollectionFactory')
             ->create()
             ->getItems();
 
diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message.php b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message.php
index 02c9732fd2d68dd98a63c8b174634e35c6d2a009..7327f57113af592ecfab1160c0347fbebccc0272 100644
--- a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message.php
+++ b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message.php
@@ -37,7 +37,7 @@ $quote->setReservedOrderId('test_order_item_with_message')
 $quote->collectTotals()->save();
 
 /** @var \Magento\GiftMessage\Model\Message $message */
-$message = $objectManager->create('\Magento\GiftMessage\Model\Message');
+$message = $objectManager->create('Magento\GiftMessage\Model\Message');
 $message->setSender('John Doe');
 $message->setRecipient('Jane Roe');
 $message->setMessage('Gift Message Text');
diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message_rollback.php b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message_rollback.php
index c71266ff03aa80c2f0c0767897974d0ed5d5cdd0..3e591550b0f564c02e1f5c1b3e22c1bf3dd98b8d 100644
--- a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_item_message_rollback.php
@@ -9,7 +9,7 @@ $registry->register('isSecureArea', true);
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 $quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('test_order_item_with_message', 'reserved_order_id');
-$message = $objectManager->create('\Magento\GiftMessage\Model\Message');
+$message = $objectManager->create('Magento\GiftMessage\Model\Message');
 $product = $objectManager->create('Magento\Catalog\Model\Product');
 foreach ($quote->getAllItems() as $item) {
     $message->load($item->getGiftMessageId());
diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message.php b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message.php
index ac79d7407e5844d7e2cb86c11e3c8b983b3e4db3..3cdc3632d358d11112b687e97a8d961969f4acf7 100644
--- a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message.php
+++ b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message.php
@@ -6,7 +6,7 @@
 $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
 
 /** @var \Magento\GiftMessage\Model\Message $message */
-$message = $objectManager->create('\Magento\GiftMessage\Model\Message');
+$message = $objectManager->create('Magento\GiftMessage\Model\Message');
 $message->setSender('Romeo');
 $message->setRecipient('Mercutio');
 $message->setMessage('I thought all for the best.');
diff --git a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message_rollback.php b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message_rollback.php
index 020bd49302f6b6805d0b4a7ddf4ba6043eaca557..d812b302dd6d87f5e99b7777dc77aed1aa7c5738 100644
--- a/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/GiftMessage/_files/quote_with_message_rollback.php
@@ -10,7 +10,7 @@ $quote = $objectManager->create('Magento\Sales\Model\Quote');
 $quote->load('message_order_21', 'reserved_order_id');
 
 /** @var \Magento\GiftMessage\Model\Message $message */
-$message = $objectManager->create('\Magento\GiftMessage\Model\Message');
+$message = $objectManager->create('Magento\GiftMessage\Model\Message');
 $message->load($quote->getGiftMessageId());
 $message->delete();
 
diff --git a/dev/tests/integration/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php b/dev/tests/integration/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
index 9dfd1848d3d2e53c649b53a02b6253462083f347..7192622e0c53b7ef4503e5ad776c81b2e6077415 100644
--- a/dev/tests/integration/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
@@ -25,8 +25,8 @@ class AuthorizationServiceTest extends \PHPUnit_Framework_TestCase
     {
         parent::setUp();
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $loggerMock = $this->getMockBuilder('Magento\\Framework\\Logger')->disableOriginalConstructor()->getMock();
-        $loggerMock->expects($this->any())->method('logException')->will($this->returnSelf());
+        $loggerMock = $this->getMockBuilder('Psr\\Log\\LoggerInterface')->disableOriginalConstructor()->getMock();
+        $loggerMock->expects($this->any())->method('critical')->will($this->returnSelf());
         $this->_service = $objectManager->create(
             'Magento\Integration\Service\V1\AuthorizationService',
             [
diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Block/Checkout/Address/SelectTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Block/Checkout/Address/SelectTest.php
index 9f4f37ead612ad8b175b5f4f3e421341f79852e5..ba1ea5ac55ff112e6bae5786b53f9d6116b8c5a9 100644
--- a/dev/tests/integration/testsuite/Magento/Multishipping/Block/Checkout/Address/SelectTest.php
+++ b/dev/tests/integration/testsuite/Magento/Multishipping/Block/Checkout/Address/SelectTest.php
@@ -31,7 +31,7 @@ class SelectTest extends \PHPUnit_Framework_TestCase
     {
         /** @var \Magento\Customer\Api\AddressRepositoryInterface $addressRepository */
         $addressRepository = Bootstrap::getObjectManager()->create(
-            '\Magento\Customer\Api\AddressRepositoryInterface'
+            'Magento\Customer\Api\AddressRepositoryInterface'
         );
         $fixtureAddressId = 1;
         $address = $addressRepository->getById($fixtureAddressId);
diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
index 87bf4d582e6500191a2f5361703b7315788d982a..9e25b21ee91f5cf87ec891e791fcc243c091028a 100644
--- a/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Multishipping/Controller/CheckoutTest.php
@@ -31,7 +31,7 @@ class CheckoutTest extends \Magento\TestFramework\TestCase\AbstractController
             ->setQuoteId($quote->getId());
 
         $formKey = $this->_objectManager->get('Magento\Framework\Data\Form\FormKey');
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
 
         /** @var $session \Magento\Customer\Model\Session */
         $session = Bootstrap::getObjectManager()->create('Magento\Customer\Model\Session', [$logger]);
diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Queue/Edit/FormTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Queue/Edit/FormTest.php
index 6849d9ffd8965be04deff2a635a9765848203e11..aeee37329dfb3f633e16e2193b41b8359b295691 100644
--- a/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Queue/Edit/FormTest.php
+++ b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Adminhtml/Queue/Edit/FormTest.php
@@ -18,7 +18,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         $queue = $objectManager->get('Magento\Newsletter\Model\Queue');
         /** @var \Magento\Framework\Registry $registry */
-        $registry = $objectManager->get('\Magento\Framework\Registry');
+        $registry = $objectManager->get('Magento\Framework\Registry');
         $registry->register('current_queue', $queue);
 
         $objectManager->get(
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php
index b442c5669963d20c20dc12956d04d71fec5b0957..8c81582f654724e2e2ebf08a42f8016b1fa72ebe 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/FormTest.php
@@ -86,8 +86,8 @@ ORDER_DATA_JSON;
 
     private function setUpMockAddress()
     {
-        $regionBuilder1 = $this->_objectManager->create('\Magento\Customer\Api\Data\RegionDataBuilder');
-        $regionBuilder2 = $this->_objectManager->create('\Magento\Customer\Api\Data\RegionDataBuilder');
+        $regionBuilder1 = $this->_objectManager->create('Magento\Customer\Api\Data\RegionDataBuilder');
+        $regionBuilder2 = $this->_objectManager->create('Magento\Customer\Api\Data\RegionDataBuilder');
 
         /** @var \Magento\Customer\Api\Data\AddressDataBuilder $addressBuilder */
         $addressBuilder = $this->_objectManager->create('Magento\Customer\Api\Data\AddressDataBuilder');
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
index 5c50ad08fc109fb2b4ce3ea07f5cab3b5cb879cb..9750f9707bee9a4d8919c80b439d233342625979 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
@@ -108,7 +108,7 @@ class CreateTest extends \Magento\Backend\Utility\Controller
     public function testGetAclResource($actionName, $reordered, $expectedResult)
     {
         $this->_objectManager->get('Magento\Backend\Model\Session\Quote')->setReordered($reordered);
-        $orderController = $this->_objectManager->get('\Magento\Sales\Controller\Adminhtml\Order\Create');
+        $orderController = $this->_objectManager->get('Magento\Sales\Controller\Adminhtml\Order\Create');
 
         $this->getRequest()->setActionName($actionName);
 
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/QuoteTest.php
index 2bfff2ec25567d55f12de8c8c0f8da164c439435..356f1b8d0166c62d3a43f5d428ebaa94b0f2c30a 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Model/QuoteTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/QuoteTest.php
@@ -68,7 +68,7 @@ class QuoteTest extends \PHPUnit_Framework_TestCase
          * @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository
          */
         $customerRepository = Bootstrap::getObjectManager()
-            ->create('\Magento\Customer\Api\CustomerRepositoryInterface');
+            ->create('Magento\Customer\Api\CustomerRepositoryInterface');
         $customerRepository->save($customerDataSet);
         $quote->setCustomer($customerDataSet);
         $expected = $this->_getCustomerDataArray();
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/OrderTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/OrderTest.php
index f9da905c795cc8efb651cd2c8c7002ad0f202f24..9d10fd0bb2734fb762ae1e053b6cfa53ab6ae72c 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/OrderTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Resource/OrderTest.php
@@ -24,7 +24,7 @@ class OrderTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $this->resourceModel = $this->objectManager->create('\Magento\Sales\Model\Resource\Order');
+        $this->resourceModel = $this->objectManager->create('Magento\Sales\Model\Resource\Order');
         $this->orderIncrementId = '100000001';
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php
index 53494019e75e0ebb188d9f57b67fa065a4650d19..e61b820234045e2b750d5900331c61fa096ee175 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php
@@ -20,7 +20,7 @@ $creditmemo->setIncrementId('100000001');
 $creditmemo->save();
 
 /** @var \Magento\Sales\Model\Order\Item $orderItem */
-$orderItem = $objectManager->get('\Magento\Sales\Model\Order\Item');
+$orderItem = $objectManager->get('Magento\Sales\Model\Order\Item');
 $orderItem->setName('Test item')
     ->setQtyRefunded(1)
     ->setQtyInvoiced(10)
diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d14ae963cee1ab9c32a2e47c809f34065836cfe
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\SalesRule\Model\Resource\Report\Rule;
+
+/**
+ * Createdat test for check report totals calculate
+ *
+ * @magentoDataFixture Magento/SalesRule/_files/order_with_coupon.php
+ */
+class CreatedatTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider orderParamsDataProvider()
+     * @param $orderParams
+     */
+    public function testTotals($orderParams)
+    {
+        /** @var \Magento\Sales\Model\Order $order */
+        $order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Sales\Model\Order');
+        $order->loadByIncrementId('100000001')
+            ->setBaseGrandTotal($orderParams['base_subtotal'])
+            ->setSubtotal($orderParams['base_subtotal'])
+            ->setBaseSubtotal($orderParams['base_subtotal'])
+            ->setBaseDiscountAmount($orderParams['base_discount_amount'])
+            ->setBaseTaxAmount($orderParams['base_tax_amount'])
+            ->setBaseSubtotalInvoiced($orderParams['base_subtotal_invoiced'])
+            ->setBaseDiscountInvoiced($orderParams['base_discount_invoiced'])
+            ->setBaseTaxInvoiced($orderParams['base_tax_invoiced'])
+            ->setBaseShippingAmount(0)
+            ->setBaseToGlobalRate(1)
+            ->setCouponCode('1234567890')
+            ->setCreatedAt('2014-10-25 10:10:10')
+            ->save();
+        // refresh report statistics
+        /** @var \Magento\SalesRule\Model\Resource\Report\Rule $reportResource */
+        $reportResource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\SalesRule\Model\Resource\Report\Rule'
+        );
+        $reportResource->aggregate();
+        /** @var \Magento\SalesRule\Model\Resource\Report\Collection $reportCollection */
+        $reportCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            'Magento\SalesRule\Model\Resource\Report\Collection'
+        );
+        $salesRuleReportItem = $reportCollection->getFirstItem();
+        $this->assertEquals($this->getTotalAmount($order), $salesRuleReportItem['total_amount']);
+        $this->assertEquals($this->getTotalAmountActual($order), $salesRuleReportItem['total_amount_actual']);
+    }
+
+    /**
+     * Repeat sql formula from \Magento\SalesRule\Model\Resource\Report\Rule\Createdat::_aggregateByOrder
+     *
+     * @param \Magento\Sales\Model\Order $order
+     * @return float
+     */
+    private function getTotalAmount(\Magento\Sales\Model\Order $order)
+    {
+        return (
+            $order->getBaseSubtotal() - $order->getBaseSubtotalCanceled()
+            - (abs($order->getBaseDiscountAmount()) - abs($order->getBaseDiscountCanceled()))
+            + ($order->getBaseTaxAmount() - $order->getBaseTaxCanceled())
+        ) * $order->getBaseToGlobalRate();
+    }
+
+    /**
+     * Repeat sql formula from \Magento\SalesRule\Model\Resource\Report\Rule\Createdat::_aggregateByOrder
+     *
+     * @param \Magento\Sales\Model\Order $order
+     * @return float
+     */
+    private function getTotalAmountActual(\Magento\Sales\Model\Order $order)
+    {
+        return (
+            $order->getBaseSubtotalInvoiced() - $order->getSubtotalRefunded()
+            - abs($order->getBaseDiscountInvoiced()) - abs($order->getBaseDiscountRefunded())
+            + $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded()
+        ) * $order->getBaseToGlobalRate();
+    }
+
+    /**
+     * @return array
+     */
+    public function orderParamsDataProvider()
+    {
+        return [
+            [
+                [
+                    'base_discount_amount' => 98.80,
+                    'base_subtotal' => 494,
+                    'base_tax_amount' => 8.8,
+                    'base_subtotal_invoiced' => 494,
+                    'base_discount_invoiced' => 98.80,
+                    'base_tax_invoiced' => 8.8
+                ]
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php b/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php
index c0f8365317556ade4bb01e518825e00f7c0cac8c..2e88e9f1fd658d6428c75cce3b4ca9f20fc6a981 100644
--- a/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php
@@ -53,7 +53,7 @@ class SendTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetCustomerFieldFromSession($field, $value)
     {
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         /** @var $session \Magento\Customer\Model\Session */
         $session = Bootstrap::getObjectManager()->create('Magento\Customer\Model\Session', [$logger]);
         /** @var \Magento\Customer\Api\AccountManagementInterface $service */
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
index fbe320324299906da720bf66a72c16b90eccc854..6f24cee659703a707ff04dfa328cc8444234e53e 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
@@ -106,11 +106,11 @@ class SubtotalTest extends \PHPUnit_Framework_TestCase
         $address = $quote->getShippingAddress();
 
         /** @var \Magento\Sales\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
-        $addressSubtotalCollector = $this->objectManager->create('\Magento\Sales\Model\Quote\Address\Total\Subtotal');
+        $addressSubtotalCollector = $this->objectManager->create('Magento\Sales\Model\Quote\Address\Total\Subtotal');
         $addressSubtotalCollector->collect($address);
 
         /** @var \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subtotalCollector */
-        $subtotalCollector = $this->objectManager->create('\Magento\Tax\Model\Sales\Total\Quote\Subtotal');
+        $subtotalCollector = $this->objectManager->create('Magento\Tax\Model\Sales\Total\Quote\Subtotal');
         $subtotalCollector->collect($address);
 
         $this->assertEquals($expected['subtotal'], $address->getSubtotal());
@@ -221,11 +221,11 @@ class SubtotalTest extends \PHPUnit_Framework_TestCase
         $address = $quote->getShippingAddress();
 
         /** @var \Magento\Sales\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
-        $addressSubtotalCollector = $this->objectManager->create('\Magento\Sales\Model\Quote\Address\Total\Subtotal');
+        $addressSubtotalCollector = $this->objectManager->create('Magento\Sales\Model\Quote\Address\Total\Subtotal');
         $addressSubtotalCollector->collect($address);
 
         /** @var \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subtotalCollector */
-        $subtotalCollector = $this->objectManager->create('\Magento\Tax\Model\Sales\Total\Quote\Subtotal');
+        $subtotalCollector = $this->objectManager->create('Magento\Tax\Model\Sales\Total\Quote\Subtotal');
         $subtotalCollector->collect($address);
 
         $this->assertEquals($expected['subtotal'], $address->getSubtotal());
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php
index 94bcf24352b16bfd9c3d816990bcb9fac6695b67..f6ef2eced2db724e13d211dff8d906144e443e80 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php
@@ -27,7 +27,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
         $source = Bootstrap::getObjectManager()->get('Magento\Tax\Model\TaxClass\Source\Customer');
         $this->assertEquals(
             $expectedResult,
-            $source->getAllOptions(false),
+            $source->getAllOptions(),
             'Tax Class options are invalid.'
         );
     }
@@ -46,7 +46,6 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
         if (empty($expectedResult)) {
             $this->fail('Preconditions failed: At least one tax class should be available.');
         }
-        $expectedResult = array_merge([['value' => '0', 'label' => __('None')]], $expectedResult);
         /** @var \Magento\Tax\Model\TaxClass\Source\Product $source */
         $source = Bootstrap::getObjectManager()->get('Magento\Tax\Model\TaxClass\Source\Customer');
         $this->assertEquals(
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php
index 9d67c1a1ba1f32452e3a551b12619ae0e3eeb080..57d6eec4bbc59c6741a420bcc9a7aad3cc9b4474 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxRuleRepositoryTest.php
@@ -310,7 +310,7 @@ class TaxRuleRepositoryTest extends \PHPUnit_Framework_TestCase
 
     public function searchTaxRulesDataProvider()
     {
-        $filterBuilder = Bootstrap::getObjectManager()->create('\Magento\Framework\Api\FilterBuilder');
+        $filterBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder');
 
         return [
             'code eq "Default Rule"' => [
diff --git a/dev/tests/integration/testsuite/Magento/Translation/Model/InlineParserTest.php b/dev/tests/integration/testsuite/Magento/Translation/Model/InlineParserTest.php
index e8e777f10bf005b6eaf5f286394a7978c97a001d..21aca63de45299c1646b7ad80c7e4fdf73a8be8e 100644
--- a/dev/tests/integration/testsuite/Magento/Translation/Model/InlineParserTest.php
+++ b/dev/tests/integration/testsuite/Magento/Translation/Model/InlineParserTest.php
@@ -62,8 +62,8 @@ class InlineParserTest extends \PHPUnit_Framework_TestCase
         } catch (\Exception $e) {
             $model->delete();
             \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-                ->get('Magento\Framework\Logger')
-                ->logException($e);
+                ->get('Psr\Log\LoggerInterface')
+                ->critical($e);
         }
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Model/PathProcessorTest.php b/dev/tests/integration/testsuite/Magento/Webapi/Model/PathProcessorTest.php
index 0f881df4bc9fc6ea1e82ca48a9555f6f2c2b30d1..3b159bc71b4fef4f79706512e9fd4f3b4e3970cf 100644
--- a/dev/tests/integration/testsuite/Magento/Webapi/Model/PathProcessorTest.php
+++ b/dev/tests/integration/testsuite/Magento/Webapi/Model/PathProcessorTest.php
@@ -21,7 +21,7 @@ class PathProcessorTest extends \PHPUnit_Framework_TestCase
     {
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         $this->storeManager = $objectManager->get('Magento\Store\Model\StoreManagerInterface');
-        $this->pathProcessor = $objectManager->get('\Magento\Webapi\Model\PathProcessor');
+        $this->pathProcessor = $objectManager->get('Magento\Webapi\Model\PathProcessor');
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
index 3fea90233aa3fa6b4e48ae17e506338e132ae630..26cb4a3747ab7d184aa175f93e7bffc58b72fe5c 100644
--- a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
+++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php
@@ -24,7 +24,7 @@ class IndexTest extends \Magento\TestFramework\TestCase\AbstractController
     protected function setUp()
     {
         parent::setUp();
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface', [], [], '', false);
         $this->_customerSession = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\Customer\Model\Session',
             [$logger]
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
index 1d55de7b2756da549f1f0657a43e5146a24b7ea3..c6bac2ba9f3b3dd5970b717f88acea5427bb38bb 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/reference.txt
@@ -37,3 +37,17 @@ Model3
 \Magento\Wonderland\Model\Data\FakeRegion
 \Magento\Wonderland\Model\Data\FakeAddress
 \Magento\Framework\Error\Processor
+\Magento\TestModule3\Service\V1\Entity\Parameter
+\Magento\TestModule3\Service\V1\Entity\ParameterBuilder
+\Magento\TestModuleMSC\Api\Data\ItemInterface
+\Magento\TestModule5\Service\V1\Entity\AllSoapAndRest
+\Magento\TestModule5\Service\V2\Entity\AllSoapAndRest
+\Magento\TestModule5\Service\V2\Entity\AllSoapAndRestBuilder
+\Magento\TestModule1\Service\V1\Entity\Item
+\Magento\TestModule1\Service\V1\Entity\ItemBuilder
+\Magento\TestModule1\Service\V2\Entity\Item
+\Magento\TestModule1\Service\V2\Entity\ItemBuilder
+\Magento\TestModule2\Service\V1\Entity\Item
+\Magento\TestModule2\Service\V1\Entity\ItemBuilder
+\Magento\TestModule4\Service\V1\Entity\DataObjectResponse
+\Magento\TestModule4\Service\V1\Entity\DataObjectRequest
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
index f89a0ded5448b9d45388a1b93b76bf58a19c2746..e145ee1a92be2c4687e228f04f015b6fde9ab3a0 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
@@ -1724,7 +1724,7 @@ return [
     ['Magento\Adminhtml\Block\Report\Wishlist', 'Magento\Reports\Block\Adminhtml\Wishlist'],
     ['Magento\Backend\Helper\Addresses'],
     ['Magento\Core\Model\Cookie', 'Magento\Framework\Stdlib\Cookie'],
-    ['Magento\Core\Model\Logger', 'Magento\Framework\Logger'],
+    ['Magento\Core\Model\Logger', 'Psr\Log\LoggerInterface'],
     ['Magento\Core\Block\Template\Context', 'Magento\Framework\View\Element\Template\Context'],
     ['Magento\Page\Block\Template\Container'],
     ['Magento\Page\Block\Redirect', 'Magento\Framework\View\Element\Redirect'],
@@ -2329,8 +2329,9 @@ return [
     ['Magento\TranslateInterface', 'Magento\Framework\TranslateInterface'],
     ['Magento\Locale', 'Magento\Framework\Locale'],
     ['Magento\LocaleFactory', 'Magento\Framework\LocaleFactory'],
+    ['Magento\Integration\Model\Oauth\Token\Factory', 'Magento\Integration\Model\Oauth\TokenFactory'],
     ['Magento\LocaleInterface', 'Magento\Framework\LocaleInterface'],
-    ['Magento\Logger', 'Magento\Framework\Logger'],
+    ['Magento\Logger', 'Psr\Log\LoggerInterface'],
     ['Magento\Phrase', 'Magento\Framework\Phrase'],
     ['Magento\Pear', 'Magento\Framework\Pear'],
     [
@@ -2842,4 +2843,5 @@ return [
     ['Magento\Rule\Model\Rule', 'Magento\Rule\Model\AbstractModel'],
     ['Magento\Framework\App\Cache\State\Options', 'Magento\Framework\App\Cache\State'],
     ['Magento\Framework\App\Cache\State\OptionsInterface', 'Magento\Framework\App\Cache\State'],
+    ['Magento\Framework\Logger', 'Psr\Log\LoggerInterface'],
 ];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index 5b3c80f4e523a22dce1f42b0e83ce78114022d0d..425044b2bdd626b6dea92862fe818cc8b1a239c4 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -1929,7 +1929,7 @@ return [
     ['setTablePrefix', 'Magento\Framework\App\Magento\Framework\App\Resource', 'Can be passed through constructor only'],
     ['_debugTimer', 'Magento\Framework\DB\Adapter\Pdo\Mysql', 'Magento\Framework\DB\Logger\LoggerAbstract::startTimer'],
     ['_debugStat', 'Magento\Framework\DB\Adapter\Pdo\Mysql', 'Magento\Framework\DB\Logger\File::logStats'],
-    ['_debugException', 'Magento\Framework\DB\Adapter\Pdo\Mysql', 'Magento\Framework\DB\Logger\File::logException'],
+    ['_debugException', 'Magento\Framework\DB\Adapter\Pdo\Mysql', 'Magento\Framework\DB\Logger\File::critical'],
     ['_debugWriteToFile', 'Magento\Framework\DB\Adapter\Pdo\Mysql', 'Magento\Framework\DB\Logger\File::log'],
     ['applyDataUpdates', 'Magento\Framework\Module\Setup', 'Magento\Framework\Module\DataSetup::applyDataUpdates'],
     ['_installData', 'Magento\Framework\Module\Setup', 'Magento\Framework\Module\DataSetup::_installData'],
@@ -2001,6 +2001,11 @@ return [
     ['getScriptTranslation', 'Magento\Framework\LocaleInterface'],
     ['getCountryTranslation', 'Magento\Framework\LocaleInterface'],
     ['getTerritoryTranslation', 'Magento\Framework\LocaleInterface'],
+    [
+        'getNoteNotify',
+        'Magento\Sales\Block\Adminhtml\Order\Create\Comment',
+        'Magento\Sales\Block\Adminhtml\Order\Create\Totals'
+    ],
     ['getLinksConfig', 'Magento\Downloadable\Block\Catalog\Product\Links'],
     ['getAuthorizationAmounts', 'Magento\Paypal\Model\Config'],
     ['cleanTransactions', 'Magento\Paypal\Model\Observer']
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_namespaces.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_namespaces.php
index 6892d99ff7d206fe3c2ba0ff2ad25e2ab243e628..469e282ce54fa7946f51b9fbe4e7725a18de1c75 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_namespaces.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_namespaces.php
@@ -28,7 +28,7 @@ return [
     ['Magento\Phrase', 'Magento\Framework\Phrase'],
     ['Magento\Locale', 'Magento\Framework\Locale'],
     ['Magento\Message', 'Magento\Framework\Message'],
-    ['Magento\Logger', 'Magento\Framework\Logger'],
+    ['Magento\Logger', 'Psr\Log\LoggerInterface'],
     ['Magento\Error', 'Magento\Framework\Error'],
     ['Magento\Filter', 'Magento\Framework\Filter'],
     ['Magento\DomDocument', 'Magento\Framework\DomDocument'],
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
index 06922811fcf6b5603f6e0768dc3bf15cec5bc890..9edcd2c881a181af30d129027c2c91187e58a132 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
@@ -22,7 +22,7 @@ return [
     ['_childGroups', 'Magento\Core\Block\AbstractBlock'],
     ['_combineHistory'],
     ['_config', 'Magento\Core\Model\Design\Package'],
-    ['_config', 'Magento\Framework\Logger', '_dirs'],
+    ['_config', 'Psr\Log\LoggerInterface', '_dirs'],
     ['_config', 'Magento\Core\Model\Resource\Setup'],
     ['_configModel', 'Magento\Backend\Model\Menu\AbstractDirector'],
     ['_connectionConfig', 'Magento\Core\Model\Resource\Setup'],
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
index 89690a5dd630054c8c4bddbf318749ef6162600b..083fbe5c84c2fbab4e519adeb8e61f21d67feacb 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt
@@ -144,3 +144,4 @@ app/code/Magento/Sales/Model/Spi
 Magento/Catalog/Model/ProductLink
 Magento/GroupedProduct/Model/Resource/Product/Type/Grouped
 lib/internal/Magento/Framework/Interception/ObjectManager/Config
+app/code/Magento/OfflinePayments/Model
\ No newline at end of file
diff --git a/dev/tests/unit/framework/Magento/Test/Block/Adminhtml.php b/dev/tests/unit/framework/Magento/Test/Block/Adminhtml.php
index 8080328c0f1aee3c1ee6071f2a3127828e5aee31..865cc78c1d92f0c85ed8a9a1b99260ef09f8644d 100644
--- a/dev/tests/unit/framework/Magento/Test/Block/Adminhtml.php
+++ b/dev/tests/unit/framework/Magento/Test/Block/Adminhtml.php
@@ -82,7 +82,7 @@ class Adminhtml extends \PHPUnit_Framework_TestCase
         $this->_urlMock             = $this->_makeMock('Magento\Framework\UrlInterface');
         $this->_eventManagerMock    = $this->_makeMock('Magento\Framework\Event\ManagerInterface');
         $this->_controllerMock      = $this->_makeMock('Magento\Framework\App\FrontController');
-        $this->_loggerMock          = $this->_makeMock('Magento\Framework\Logger');
+        $this->_loggerMock          = $this->_makeMock('Psr\Log\LoggerInterface');
         $this->_filesystemMock      = $this->_makeMock('Magento\Framework\Filesystem');
         $this->_cacheMock           = $this->_makeMock('Magento\Framework\App\CacheInterface');
         $this->_scopeConfigMock     = $this->_makeMock('Magento\Framework\App\Config\ScopeConfigInterface');
diff --git a/dev/tests/unit/testsuite/Magento/Authorization/Model/Acl/AclRetrieverTest.php b/dev/tests/unit/testsuite/Magento/Authorization/Model/Acl/AclRetrieverTest.php
index 72906ff1a521e12de5fcb1f56ad0043d9e01a497..a1e39651e62085757c512a855463b9b8d434d7c6 100644
--- a/dev/tests/unit/testsuite/Magento/Authorization/Model/Acl/AclRetrieverTest.php
+++ b/dev/tests/unit/testsuite/Magento/Authorization/Model/Acl/AclRetrieverTest.php
@@ -165,7 +165,7 @@ class AclRetrieverTest extends \PHPUnit_Framework_TestCase
             $aclBuilderMock,
             $roleCollectionFactoryMock,
             $rulesCollectionFactoryMock,
-            $this->getMock('Magento\Framework\Logger', [], [], '', false)
+            $this->getMock('Psr\Log\LoggerInterface')
         );
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/TunnelTest.php b/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/TunnelTest.php
index c7a5f978517553ab559812154ad05afb6cb2b069..58b3541dd4cf0fbaf7c6810c5285fdacbb17178e 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/TunnelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Controller/Adminhtml/Dashboard/TunnelTest.php
@@ -142,11 +142,11 @@ class TunnelTest extends \PHPUnit_Framework_TestCase
             ->method('create')
             ->with('Magento\Framework\HTTP\ZendClient')
             ->will($this->throwException($exceptionMock));
-        $loggerMock = $this->getMock('Magento\Framework\Logger', ['logException'], [], '', false);
-        $loggerMock->expects($this->once())->method('logException')->with($exceptionMock);
+        $loggerMock = $this->getMock('Psr\Log\LoggerInterface');
+        $loggerMock->expects($this->once())->method('critical')->with($exceptionMock);
         $this->_objectManager->expects($this->at(2))
             ->method('get')
-            ->with('Magento\Framework\Logger')
+            ->with('Psr\Log\LoggerInterface')
             ->will($this->returnValue($loggerMock));
 
         $controller = $this->_factory($this->_request, $this->_response);
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/BaseurlTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/BaseurlTest.php
index 4434ebbb8ee12e6832344c497ddb0c7807f34e70..dc5dd79a794c3eee6127fa08a45f639c4ee35000 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/BaseurlTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/BaseurlTest.php
@@ -11,7 +11,7 @@ class BaseurlTest extends \PHPUnit_Framework_TestCase
         $eventDispatcher = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $appState = $this->getMock('Magento\Framework\App\State', [], [], '', false);
         $cacheManager = $this->getMock('Magento\Framework\App\CacheInterface');
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $actionValidatorMock = $this->getMock(
             'Magento\Framework\Model\ActionValidator\RemoveAction',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/SecureTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/SecureTest.php
index d1a38f433c5f5bf3326211988497f0599b6e0a64..8d8c30a7dd7ea9a4830ae3d8755e466564f017c5 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/SecureTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Backend/SecureTest.php
@@ -11,7 +11,7 @@ class SecureTest extends \PHPUnit_Framework_TestCase
         $eventDispatcher = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $appState = $this->getMock('Magento\Framework\App\State', [], [], '', false);
         $cacheManager = $this->getMock('Magento\Framework\App\CacheInterface');
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $actionValidatorMock = $this->getMock(
             '\Magento\Framework\Model\ActionValidator\RemoveAction',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Source/Admin/PageTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Source/Admin/PageTest.php
index 1fff5d361bb37e47d7f0108f18ddd8516fc3a4ff..7e7fbee400dba5c77da2e32367b6bb33c5e8c103 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Source/Admin/PageTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Config/Source/Admin/PageTest.php
@@ -32,7 +32,7 @@ class PageTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->_menuModel = new \Magento\Backend\Model\Menu($logger);
         $this->_menuSubModel = new \Magento\Backend\Model\Menu($logger);
 
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/BuilderTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/BuilderTest.php
index 25e7413aa295d0a9649b8bfb6eac42d54b030fd8..b4880b7154cb4775843d368c5b6062dfb5953933 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/BuilderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/BuilderTest.php
@@ -27,7 +27,7 @@ class BuilderTest extends \PHPUnit_Framework_TestCase
         $this->_menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
 
         $this->_model = new \Magento\Backend\Model\Menu\Builder($this->_factoryMock, $this->_menuMock);
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ConfigTest.php
index 097ab1634ebce95ec740271fbc9fa443d356919a..bc5f314e0618de34a38676afc9161df173687a88 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ConfigTest.php
@@ -94,18 +94,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
             false
         );
 
-        $this->_logger = $this->getMock(
-            'Magento\Framework\Logger',
-            ['addStoreLog', 'log', 'logException'],
-            [],
-            '',
-            false
-        );
+        $this->_logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->_menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
 
         $this->_menuBuilderMock = $this->getMock('Magento\Backend\Model\Menu\Builder', [], [], '', false);
@@ -210,7 +204,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
 
     public function testGetMenuGenericExceptionIsNotLogged()
     {
-        $this->_logger->expects($this->never())->method('logException');
+        $this->_logger->expects($this->never())->method('critical');
 
         $this->_menuBuilderMock->expects(
             $this->exactly(1)
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Director/DirectorTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Director/DirectorTest.php
index 5a459132fa47c10e8d9adb5f51771dbd85ad80ca..696043006c9bc6c69faa027fc3730b51f4700ef1 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Director/DirectorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Director/DirectorTest.php
@@ -38,13 +38,7 @@ class DirectorTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->_builderMock = $this->getMock('Magento\Backend\Model\Menu\Builder', [], [], '', false);
-        $this->_logger = $this->getMock(
-            'Magento\Framework\Logger',
-            ['addStoreLog', 'log', 'logException'],
-            [],
-            '',
-            false
-        );
+        $this->_logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->_commandMock = $this->getMock(
             'Magento\Backend\Model\Menu\Builder\AbstractCommand',
             ['getId', '_execute', 'execute', 'chain'],
@@ -75,7 +69,7 @@ class DirectorTest extends \PHPUnit_Framework_TestCase
     {
         $config = [['type' => 'update'], ['type' => 'remove'], ['type' => 'added']];
         $this->_builderMock->expects($this->at(2))->method('processCommand')->with($this->_commandMock);
-        $this->_logger->expects($this->at(1))->method('logDebug');
+        $this->_logger->expects($this->at(1))->method('debug');
         $this->_commandMock->expects($this->at(1))->method('getId');
         $this->_model->direct($config, $this->_builderMock, $this->_logger);
     }
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Filter/IteratorTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Filter/IteratorTest.php
index a1f3c38ae4a63c6709a488f417164e16db2850e6..080cd564b174ef7822a2ffa6eb7da9edabdbd0ff 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Filter/IteratorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/Filter/IteratorTest.php
@@ -38,7 +38,7 @@ class IteratorTest extends \PHPUnit_Framework_TestCase
         $this->_items['item3']->expects($this->any())->method('isDisabled')->will($this->returnValue(false));
         $this->_items['item3']->expects($this->any())->method('isAllowed')->will($this->returnValue(false));
 
-        $loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->_menuModel = new \Magento\Backend\Model\Menu($loggerMock);
         $this->_filterIteratorModel = new \Magento\Backend\Model\Menu\Filter\Iterator(
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ItemTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ItemTest.php
index e7ce46a61dcaaeaee875be2f8d8895233f1d9018..30d52ab0419daec4c63c855fe1edac307752bfbc 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ItemTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Menu/ItemTest.php
@@ -217,7 +217,7 @@ class ItemTest extends \PHPUnit_Framework_TestCase
         $menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
 
         $this->_menuFactoryMock->expects($this->once())->method('create')->will($this->returnValue($menuMock));
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/MenuTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/MenuTest.php
index ade079a7984a9d202ef1987bf84d82dcd8f57acf..f788228c365bee6a924cf171407235644c13a040 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/MenuTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/MenuTest.php
@@ -12,7 +12,7 @@ class MenuTest extends \PHPUnit_Framework_TestCase
     protected $_model;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -32,7 +32,7 @@ class MenuTest extends \PHPUnit_Framework_TestCase
         $this->_items['item3'] = $this->getMock('Magento\Backend\Model\Menu\Item', [], [], '', false);
         $this->_items['item3']->expects($this->any())->method('getId')->will($this->returnValue('item3'));
 
-        $this->_logger = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
+        $this->_logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->_model = new \Magento\Backend\Model\Menu($this->_logger);
     }
@@ -47,14 +47,6 @@ class MenuTest extends \PHPUnit_Framework_TestCase
 
     public function testAddDoLogAddAction()
     {
-        $this->_logger->expects(
-            $this->once()
-        )->method(
-            'log'
-        )->with(
-            $this->equalTo(sprintf('Add of item with id %s was processed', $this->_items['item1']->getId()))
-        );
-
         $this->_model->add($this->_items['item1']);
     }
 
@@ -136,7 +128,7 @@ class MenuTest extends \PHPUnit_Framework_TestCase
         $subMenu = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
         $subMenu->expects($this->once())->method("add")->with($this->_items['item3']);
 
@@ -189,7 +181,7 @@ class MenuTest extends \PHPUnit_Framework_TestCase
         $menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
         $menuMock->expects($this->once())->method('remove')->with($this->equalTo('item2'));
 
@@ -203,15 +195,6 @@ class MenuTest extends \PHPUnit_Framework_TestCase
     public function testRemoveDoLogRemoveAction()
     {
         $this->_model->add($this->_items['item1']);
-
-        $this->_logger->expects(
-            $this->once()
-        )->method(
-            'log'
-        )->with(
-            $this->equalTo(sprintf('Remove on item with id %s was processed', $this->_items['item1']->getId()))
-        );
-
         $this->_model->remove('item1');
     }
 
@@ -335,7 +318,6 @@ class MenuTest extends \PHPUnit_Framework_TestCase
     public function testSerialize()
     {
         $this->assertNotEmpty($this->_model->serialize());
-        $this->_logger->expects($this->once())->method('log');
         $this->_model->add($this->_items['item1']);
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/Translate/Inline/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/Translate/Inline/ConfigTest.php
index 8178a8f98b8ff0ada61286bbfeca5ca9e2a51519..6796ff7b20e60efc5fb2880b6864fca1a512992e 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/Translate/Inline/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/Translate/Inline/ConfigTest.php
@@ -21,7 +21,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $config = $objectManager->getObject(
-            '\Magento\Backend\Model\Translate\Inline\Config',
+            'Magento\Backend\Model\Translate\Inline\Config',
             ['config' => $backendConfig]
         );
         $this->assertEquals($result, $config->isActive('any'));
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Model/UrlTest.php b/dev/tests/unit/testsuite/Magento/Backend/Model/UrlTest.php
index a06bdd16060f88ed57428c75463281a87572c418..74d4b10a1eb72e206f8dc6f7acbab224fb0f63dd 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Model/UrlTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Model/UrlTest.php
@@ -77,7 +77,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase
         $this->_menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
 
         $this->_menuConfigMock = $this->getMock('Magento\Backend\Model\Menu\Config', [], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php
index 169b42dce907373118eb08564a46f4516c171cef..531e403b2b1636079bdf0c6eb34d618f1023d69b 100644
--- a/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/PriceBackendTest.php
@@ -24,7 +24,7 @@ class PriceBackendTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $objectManager = new ObjectManager($this);
-        $this->priceBackendPlugin = $objectManager->getObject('\Magento\Bundle\Model\Plugin\PriceBackend');
+        $this->priceBackendPlugin = $objectManager->getObject('Magento\Bundle\Model\Plugin\PriceBackend');
 
         $this->closure = function () {
             return static::CLOSURE_VALUE;
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/ProductTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/ProductTest.php
index aacd23afdc77ce14c2c9e2124c9f979f4ec351a0..5751d3ce99625bc8d957aa0b6ecd71570d06eb22 100644
--- a/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Plugin/ProductTest.php
@@ -34,7 +34,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->plugin = $objectManager->getObject(
-            '\Magento\Bundle\Model\Plugin\Product',
+            'Magento\Bundle\Model\Plugin\Product',
             [
                 'type' => $this->type,
             ]
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/OptionListTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/OptionListTest.php
index 4a6e8fdea8d32e60445ca017b3a476fb19a6aaa9..e8cdedd266eb91116dd328f8588742cdae38e70b 100644
--- a/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/OptionListTest.php
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Model/Product/OptionListTest.php
@@ -63,7 +63,7 @@ class OptionListTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $optionsCollMock = $objectManager->getCollectionMock(
-            '\Magento\Bundle\Model\Resource\Option\Collection',
+            'Magento\Bundle\Model\Resource\Option\Collection',
             [$optionMock]
         );
         $this->typeMock->expects($this->once())
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/CategoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/CategoryTest.php
index 416050c0d71b41bbc1ae09468d4c0edf9b717fd3..9c43306184791e5c5c5f5360e36009cb23034cfc 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/CategoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/CategoryTest.php
@@ -34,7 +34,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
             ->method('isAllowed')
             ->will($this->returnValue($isAllowed));
         $model = $this->objectManager->getObject(
-            '\Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category',
+            'Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category',
             ['authorization' => $this->authorization]
         );
         switch ($isAllowed) {
@@ -60,7 +60,7 @@ class CategoryTest extends \PHPUnit_Framework_TestCase
     public function testGetAfterElementHtml()
     {
         $model = $this->objectManager->getObject(
-            '\Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category',
+            'Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Category',
             ['authorization' => $this->authorization]
         );
         $this->authorization->expects($this->any())
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/WeightTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/WeightTest.php
index e4c9298ab9351276bb90552e41b983ff1119ad8d..02d63ad6b976785cf3c58c5c9ce56a5e9d7f0e5c 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/WeightTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/WeightTest.php
@@ -84,7 +84,7 @@ class WeightTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_model = $objectManager->getObject(
-            '\Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Weight',
+            'Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Weight',
             ['factoryElement' => $factory, 'factoryCollection' => $collectionFactory, 'helper' => $helper]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Product/BuilderTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Product/BuilderTest.php
index 06f8d57b4c979493e77a9be8cc04bb200ff2de17..cc5bec710735f26f463a1445277818f30cb5ce3b 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Product/BuilderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Controller/Adminhtml/Product/BuilderTest.php
@@ -43,7 +43,7 @@ class BuilderTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', ['create'], [], '', false);
         $this->registryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false);
         $this->wysiwygConfigMock = $this->getMock(
@@ -179,7 +179,7 @@ class BuilderTest extends \PHPUnit_Framework_TestCase
                 $this->throwException(new \Exception())
             );
         $this->loggerMock->expects($this->once())
-            ->method('logException');
+            ->method('critical');
         $this->productMock->expects($this->once())
             ->method('setAttributeSetId')
             ->with(3)
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ConfigTest.php
index 4760cbfea680d6820bdd3123a6e9d98e20265c87..06236231c14928e8f0e2063850f481e5cf32e823 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ConfigTest.php
@@ -22,7 +22,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Config',
+            'Magento\Catalog\Model\Config',
             ['setCollectionFactory' => $setCollectionFactory]
         );
         $setItem = $this->getMock(
@@ -81,7 +81,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Config',
+            'Magento\Catalog\Model\Config',
             ['groupCollectionFactory' => $groupCollectionFactory]
         );
         $setItem = $this->getMock(
@@ -137,7 +137,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $productTypeFactory = $this->getMock('\Magento\Catalog\Model\Product\TypeFactory', ['create'], [], '', false);
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Config',
+            'Magento\Catalog\Model\Config',
             ['productTypeFactory' => $productTypeFactory]
         );
         $typeCollection = $this->getMock('\Magento\Catalog\Model\Product\Type', ['getOptionArray'], [], '', false);
@@ -183,7 +183,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $object = $this->getMock('\Magento\Framework\Object', ['getAllOptions'], [], '', false);
         $object->expects($this->once())->method('getAllOptions')->will($this->returnValue($data));
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $model = $objectManager->getObject('\Magento\Catalog\Model\Config');
+        $model = $objectManager->getObject('Magento\Catalog\Model\Config');
         $this->assertEquals($expected, $model->getSourceOptionId($object, $search));
     }
 
@@ -254,7 +254,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Config',
+            'Magento\Catalog\Model\Config',
             ['configFactory' => $configFactory, 'storeManager' => $storeManager, 'eavConfig' => $eavConfig]
         );
 
@@ -314,7 +314,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $scopeConfig->expects($this->once())->method('getValue')
             ->with('catalog/frontend/default_sort_by', 'store', null)->will($this->returnValue(1));
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $model = $objectManager->getObject('\Magento\Catalog\Model\Config', ['scopeConfig' => $scopeConfig]);
+        $model = $objectManager->getObject('Magento\Catalog\Model\Config', ['scopeConfig' => $scopeConfig]);
         $this->assertEquals(1, $model->getProductListDefaultSortBy());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/ObserverTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/ObserverTest.php
index cd70ab51464d4d8e7bf02fe63d9b5ac1ca048158..7fe4c17e397fc5f9896ccbb0e79547d9dce05ba3 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/ObserverTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/ObserverTest.php
@@ -70,7 +70,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_model = $this->_objectManager->getObject(
-            '\Magento\Catalog\Model\Indexer\Product\Price\Observer',
+            'Magento\Catalog\Model\Indexer\Product\Price\Observer',
             [
                 'storeManager' => $this->_storeManagerMock,
                 'resource' => $this->_resourceMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
index d2d7da59dd89e27748344b03f84763b83a7b8a24..52b3b6a1fc88368a3db105e74db9dfba3520ed2e 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/CustomerGroupTest.php
@@ -49,7 +49,7 @@ class CustomerGroupTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($indexerMock));
 
         $this->_model = $this->_objectManager->getObject(
-            '\Magento\Catalog\Model\Indexer\Product\Price\Plugin\CustomerGroup',
+            'Magento\Catalog\Model\Indexer\Product\Price\Plugin\CustomerGroup',
             ['indexerRegistry' => $this->indexerRegistryMock]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/WebsiteTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/WebsiteTest.php
index 182203e835eae33015d7a2ad90980ddfe79b31df..3dcc701027f6c3c0deadc9f68560149052e11bbe 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/WebsiteTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/WebsiteTest.php
@@ -34,7 +34,7 @@ class WebsiteTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_model = $this->_objectManager->getObject(
-            '\Magento\Catalog\Model\Indexer\Product\Price\Plugin\Website',
+            'Magento\Catalog\Model\Indexer\Product\Price\Plugin\Website',
             ['processor' => $this->_priceProcessorMock]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
index cf4d702fa656f49e3ff6a999f2520f0e89bf7bab..f3125755230cc95bb9daf7655acf5f10748492b1 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScopeTest.php
@@ -46,7 +46,7 @@ class PriceScopeTest extends \PHPUnit_Framework_TestCase
 
 
         $this->_model = $this->_objectManager->getObject(
-            '\Magento\Catalog\Model\Indexer\Product\Price\System\Config\PriceScope',
+            'Magento\Catalog\Model\Indexer\Product\Price\System\Config\PriceScope',
             [
                 'context' => $contextMock,
                 'registry' => $registryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ObserverTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ObserverTest.php
index 8000b58eaa29cdcb6ebcccf1dc0034be3401b3de..dbb81426dd21c2848da5f50029b40acec7c33b5e 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ObserverTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ObserverTest.php
@@ -61,7 +61,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->_observer = (new ObjectManager($this))->getObject('\Magento\Catalog\Model\Observer', [
+        $this->_observer = (new ObjectManager($this))->getObject('Magento\Catalog\Model\Observer', [
             'urlFactory' => $this->_getCleanMock('\Magento\Catalog\Model\UrlFactory'),
             'categoryResource' => $this->_getCleanMock('\Magento\Catalog\Model\Resource\Category'),
             'catalogProduct' => $this->_getCleanMock('\Magento\Catalog\Model\Resource\Product'),
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php
index 2f1cb376bc792c576b71a8431160cb12fa820891..731eef5fb6cfe4613fb2f8a2924d5ce35b144864 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ActionTest.php
@@ -99,7 +99,7 @@ class ActionTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Product\Action',
+            'Magento\Catalog\Model\Product\Action',
             [
                 'eventDispatcher' => $eventManagerMock,
                 'resource' => $this->resource,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
index 217ab2d9ea209cff1c838abde89371e61622f4a6..963ae068f265537679ba80d04b5d9d38ef50defc 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
@@ -36,7 +36,7 @@ class ConditionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $helper = new ObjectManager($this);
-        $this->model = $helper->getObject('\Magento\Catalog\Model\Product\Condition');
+        $this->model = $helper->getObject('Magento\Catalog\Model\Product\Condition');
         $this->model->setTable('testTable')
             ->setPkFieldName('testFieldName');
     }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php
index a4f97b33b60a05a4fd00b324ab58c717ba88dfb3..17c4d474b1d6096341841a698e35784993f7f320 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php
@@ -26,7 +26,7 @@ class ProductLinksTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $helper = new ObjectManager($this);
-        $this->model = $helper->getObject('\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks');
+        $this->model = $helper->getObject('Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks');
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/LinkTypeProviderTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/LinkTypeProviderTest.php
index 0062cfe3a6fe5ce28648450ee0c7b036cefcc3a7..0638418b149b052173069167033b00af26636830 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/LinkTypeProviderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/LinkTypeProviderTest.php
@@ -52,7 +52,7 @@ class LinkTypeProviderTest extends \PHPUnit_Framework_TestCase
         ];
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Product\LinkTypeProvider',
+            'Magento\Catalog\Model\Product\LinkTypeProvider',
             [
                 'linkTypeBuilder' => $this->linkTypeBuilderMock,
                 'linkAttributeBuilder' => $this->linkAttributeBuilderMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/OptionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/OptionTest.php
index 5e91220127ed2167d2fdb5781476b40454c98b43..3be3f6ab782c1b9b72f0ae5fbdb03834e404082d 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/OptionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/OptionTest.php
@@ -22,7 +22,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     {
         $this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
         $objectManager = new ObjectManager($this);
-        $this->model = $objectManager->getObject('\Magento\Catalog\Model\Product\Option');
+        $this->model = $objectManager->getObject('Magento\Catalog\Model\Product\Option');
         $this->model->setProduct($this->productMock);
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/SimpleTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/SimpleTest.php
index 208968354742ad5d1ea669af8af308239ae62c04..716996ecadc9d11404b9199c7ea2ab2c8ac448f4 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/SimpleTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/SimpleTest.php
@@ -21,7 +21,7 @@ class SimpleTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
         $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $this->_model = $objectHelper->getObject(
             'Magento\Catalog\Model\Product\Type\Simple',
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/VirtualTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/VirtualTest.php
index b8f01b46c8683d4f3ab83b54ad7f6510b1c191ce..3bcc6208d146763a1fca5355670a7a2a57e27dcc 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/VirtualTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/VirtualTest.php
@@ -21,7 +21,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase
         $filesystem = $this->getMockBuilder('Magento\Framework\Filesystem')
             ->disableOriginalConstructor()
             ->getMock();
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $this->_model = $objectHelper->getObject(
             'Magento\Catalog\Model\Product\Type\Virtual',
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductAttributeGroupRepositoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductAttributeGroupRepositoryTest.php
index fa30c85ad16b6e0b19ed8472deb583897eeca5a8..db5ed390cdfb292747fd0275f7074727b25e553f 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductAttributeGroupRepositoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductAttributeGroupRepositoryTest.php
@@ -46,7 +46,7 @@ class ProductAttributeGroupRepositoryTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\ProductAttributeGroupRepository',
+            'Magento\Catalog\Model\ProductAttributeGroupRepository',
             [
                 'groupRepository' => $this->groupRepositoryMock,
                 'groupResource' => $this->groupResourceMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/ManagementTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/ManagementTest.php
index eb38e54cfb983ddc9aade769fa9d43dc39856191..ec0193d5c188166b6392bfbd7bc91ea7d1414b01 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/ManagementTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/ManagementTest.php
@@ -86,7 +86,7 @@ class ManagementTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\ProductLink\Management',
+            'Magento\Catalog\Model\ProductLink\Management',
             [
                 'productRepository' => $this->productRepositoryMock,
                 'collectionProvider' => $this->collectionProviderMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/RepositoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/RepositoryTest.php
index fd9267a2d71bfe47ccebb6ef7ac232db8990c915..6635666e29c18efcc71b09cd0f1c7469bbfdf818 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/RepositoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductLink/RepositoryTest.php
@@ -47,7 +47,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\ProductLink\Repository',
+            'Magento\Catalog\Model\ProductLink\Repository',
             [
                 'productRepository' => $this->productRepositoryMock,
                 'entityCollectionProvider' => $this->entityCollectionProviderMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Eav/AttributeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Eav/AttributeTest.php
index 3b1c80d319fc690a60917ea07269366c7b17af7e..363a40565064e132d4807036061955352534f1f2 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Eav/AttributeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Eav/AttributeTest.php
@@ -91,7 +91,7 @@ class AttributeTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->_model = $objectManager->getObject(
-                '\Magento\Catalog\Model\Resource\Eav\Attribute',
+                'Magento\Catalog\Model\Resource\Eav\Attribute',
                 [
                     'context' => $this->contextMock,
                     'productFlatIndexerProcessor' => $this->_processor,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
index b49d56d50d073eefe5aa1d16d96d114bf0715f3d..f57e9360912cd6cf12bf9b807cbd5c3b3c38dc83 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Link/Product/CollectionTest.php
@@ -76,7 +76,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->entityFactoryMock = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock('Magento\Framework\Data\Collection\Db\FetchStrategyInterface');
         $this->managerInterfaceMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
         $this->configMock = $this->getMock('Magento\Eav\Model\Config', [], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Option/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Option/CollectionTest.php
index 878c7e23d453432e8606324cc2f517fdff44ea3d..cbaa98332060ecb8d04f3b51477628306423575a 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Option/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/Product/Option/CollectionTest.php
@@ -12,7 +12,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected $collection;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -61,7 +61,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         $this->entityFactoryMock = $this->getMock(
             'Magento\Core\Model\EntityFactory', ['create'], [], '', false
         );
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock(
             'Magento\Framework\Data\Collection\Db\FetchStrategy\Query', ['fetchAll'], [], '', false
         );
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/ProductTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/ProductTest.php
index 1410fc93c6ac22a03361c2255182d6de97a6995e..2ad45ca8b2a63f96ac49123ceffe17bbc033ae2d 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Resource/ProductTest.php
@@ -44,7 +44,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->model = $objectManager->getObject(
-            '\Magento\Catalog\Model\Resource\Product',
+            'Magento\Catalog\Model\Resource\Product',
             [
                 'setFactory' => $this->setFactoryMock,
                 'typeFactory' => $this->typeFactoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/System/Config/Source/InputtypeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/System/Config/Source/InputtypeTest.php
index 4e0eb00d8c2bef11876a7f5ccdc7d271d74cc04d..40e37f28a1b443455aca2b38ee29f4d7892b1690 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/System/Config/Source/InputtypeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/System/Config/Source/InputtypeTest.php
@@ -19,7 +19,7 @@ class InputtypeTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->_helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = $this->_helper->getObject('\Magento\Catalog\Model\System\Config\Source\Inputtype');
+        $this->_model = $this->_helper->getObject('Magento\Catalog\Model\System\Config\Source\Inputtype');
     }
 
     public function testToOptionArrayIsArray()
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/BasePriceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/BasePriceTest.php
index f76f8f8f5907b5bf7076516705a58a62de186b5c..577b8abf638e09f47c66bab42a84ec16744e7df7 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/BasePriceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/BasePriceTest.php
@@ -72,7 +72,7 @@ class BasePriceTest extends \PHPUnit_Framework_TestCase
         ];
 
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->basePrice = $helper->getObject('\Magento\Catalog\Pricing\Price\BasePrice',
+        $this->basePrice = $helper->getObject('Magento\Catalog\Pricing\Price\BasePrice',
             [
                 'saleableItem' => $this->saleableItemMock,
                 'quantity' => $qty,
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Render/FinalPriceBoxTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Render/FinalPriceBoxTest.php
index 610278f691b940ce9a58b5f28c03bb20fffbb495..930c7fcbd5b8aa246bab4026ae25866a0f11a538 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Render/FinalPriceBoxTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Render/FinalPriceBoxTest.php
@@ -41,7 +41,7 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase
     protected $product;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $logger;
 
@@ -74,7 +74,7 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase
         $this->layout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false);
 
         $this->priceBox = $this->getMock('Magento\Framework\Pricing\Render\PriceBox', [], [], '', false);
-        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->layout->expects($this->any())
             ->method('getBlock')
@@ -187,7 +187,7 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase
     public function testRenderMsrpNotRegisteredException()
     {
         $this->logger->expects($this->once())
-            ->method('logException');
+            ->method('critical');
 
         $this->priceInfo->expects($this->once())
             ->method('getPrice')
diff --git a/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
index 00d68c8f7807e8d6a6d5cf1c94042864786b2e49..f43f1498795818bd0ad8999e7ee0450ae7f9b4bc 100644
--- a/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
@@ -381,7 +381,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             ['fetchAll']
         );
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $entityFactory = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
 
         $optionCollection = $this->getMock(
diff --git a/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index a425a07ea6191e20c0bc4f8c7de22de355efae7f..5914ed6ce0290faa4aca586bf520d48891bf65d6 100644
--- a/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -267,7 +267,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
 
         $this->_model = $objectManager->getObject(
-            '\Magento\CatalogImportExport\Model\Import\Product',
+            'Magento\CatalogImportExport\Model\Import\Product',
             [
                 'config' => $this->_eavConfig,
                 'optionFactory' => $this->_optionFactory,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/ShippingTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/ShippingTest.php
index 2bb94676cfc5525112f659bb3c31c9d51f23a586..0d4c5653a305791457a167a40dbb17e183354f63 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/ShippingTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/ShippingTest.php
@@ -57,7 +57,7 @@ class ShippingTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Checkout\Block\Cart\Shipping $shippingBlock */
         $shippingBlock = $this->objectManager->getObject(
-            '\Magento\Checkout\Block\Cart\Shipping',
+            'Magento\Checkout\Block\Cart\Shipping',
             ['context' => $contextMock]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/Sidebar/TotalsTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/Sidebar/TotalsTest.php
index d9afed82a88d2980d34ed45ccdf23d9a691e7b26..555b4b496cd7620a170f4bbbcdc8eefcbe064a52 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/Sidebar/TotalsTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/Sidebar/TotalsTest.php
@@ -40,7 +40,7 @@ class TotalsTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($this->quote));
 
         $this->totalsObj = $objectManager->getObject(
-            '\Magento\Checkout\Block\Cart\Sidebar\Totals',
+            'Magento\Checkout\Block\Cart\Sidebar\Totals',
             ['checkoutSession' => $checkoutSession]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/SidebarTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/SidebarTest.php
index 0c7f3897adf3d617eff429297044b2b33c602ae4..7bd683816b79c4d8d86c75fe37fd78c5d1ec77b7 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/SidebarTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Block/Cart/SidebarTest.php
@@ -143,7 +143,7 @@ class SidebarTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Checkout\Block\Cart\SideBar $sidebarBlock */
         $sidebarBlock = $this->_objectManager->getObject(
-            '\Magento\Checkout\Block\Cart\SideBar',
+            'Magento\Checkout\Block\Cart\SideBar',
             ['context' => $contextMock]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Block/Onepage/AbstractOnepageTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Block/Onepage/AbstractOnepageTest.php
index 04fa9ed514658c18eeb7d3e3289533cf4a1ebbae..e0eed207ba009127189d7aa80c208b8f9c9145e8 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Block/Onepage/AbstractOnepageTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Block/Onepage/AbstractOnepageTest.php
@@ -57,7 +57,7 @@ class AbstractOnepageTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Checkout\Block\Onepage\AbstractOnepage $onepage */
         $onepage = $this->objectManager->getObject(
-            '\Magento\Checkout\Block\Cart\Shipping',
+            'Magento\Checkout\Block\Cart\Shipping',
             ['context' => $contextMock]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Block/Shipping/PriceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Block/Shipping/PriceTest.php
index 3aecb126e51225f95a4119a4e600e0eaf3fcd28b..9194999d94bfcb6383e8d82ee0e0292bc61beb53 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Block/Shipping/PriceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Block/Shipping/PriceTest.php
@@ -36,7 +36,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
         $this->priceCurrency = $this->getMockBuilder('Magento\Framework\Pricing\PriceCurrencyInterface')->getMock();
 
         $this->priceObj = $objectManager->getObject(
-            '\Magento\Checkout\Block\Shipping\Price',
+            'Magento\Checkout\Block\Shipping\Price',
             ['priceCurrency'   => $this->priceCurrency]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Controller/Onepage/IndexTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Controller/Onepage/IndexTest.php
index 6a015a401c4b5602ae389a3277b3c44661a8f347..662d082c6fb3e6d2b161205259cfddac79f9622a 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Controller/Onepage/IndexTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Controller/Onepage/IndexTest.php
@@ -144,7 +144,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase
 
         // SUT
         $this->model = $this->objectManager->getObject(
-            '\Magento\Checkout\Controller\Onepage\Index',
+            'Magento\Checkout\Controller\Onepage\Index',
             [
                 'context' => $this->contextMock,
                 'customerSession' => $this->sessionMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Model/SessionTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Model/SessionTest.php
index 54ee170aa571c30eb3e640ea6520d6432eadf37d..d5bb6fe1b0ff19c8c18201c4e085f35856f0de08 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Model/SessionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Model/SessionTest.php
@@ -344,7 +344,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase
     public function testResetCheckout()
     {
         /** @var $session \Magento\Checkout\Model\Session */
-        $session = $this->_helper->getObject('\Magento\Checkout\Model\Session', [
+        $session = $this->_helper->getObject('Magento\Checkout\Model\Session', [
             'storage' => new \Magento\Framework\Session\Storage()
         ]);
         $session->resetCheckout();
@@ -360,7 +360,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase
             ],
         ];
         /** @var $session \Magento\Checkout\Model\Session */
-        $session = $this->_helper->getObject('\Magento\Checkout\Model\Session', [
+        $session = $this->_helper->getObject('Magento\Checkout\Model\Session', [
             'storage' => new \Magento\Framework\Session\Storage()
         ]);
         $session->setSteps($stepData);
@@ -379,7 +379,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase
             ],
         ];
         /** @var $session \Magento\Checkout\Model\Session */
-        $session = $this->_helper->getObject('\Magento\Checkout\Model\Session', [
+        $session = $this->_helper->getObject('Magento\Checkout\Model\Session', [
             'storage' => new \Magento\Framework\Session\Storage()
         ]);
         $session->setSteps($stepData);
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Model/Type/OnepageTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Model/Type/OnepageTest.php
index 7db6a77aa9e3ead3344e1fda80732deb9f70829b..294315836209f9ca2a7e426ad58a3ff65ab75ea9 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Model/Type/OnepageTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Model/Type/OnepageTest.php
@@ -28,7 +28,7 @@ class OnepageTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Customer\Model\Url|\PHPUnit_Framework_MockObject_MockObject */
     protected $customerUrlMock;
 
-    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $loggerMock;
 
     /** @var \Magento\Checkout\Model\Session|\PHPUnit_Framework_MockObject_MockObject */
@@ -113,7 +113,7 @@ class OnepageTest extends \PHPUnit_Framework_TestCase
         $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
         $this->checkoutHelperMock = $this->getMock('Magento\Checkout\Helper\Data', [], [], '', false);
         $this->customerUrlMock = $this->getMock('Magento\Customer\Model\Url', [], [], '', false);
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->checkoutSessionMock = $this->getMock(
             'Magento\Checkout\Model\Session',
             ['getLastOrderId', 'getQuote', 'setStepData', 'getStepData'],
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php
index 688ceb111d5b94784cce9c1424e8141dfa929e7e..4635856766682bc3f4c8cfbf11c2398d359f2a88 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Billing/WriteServiceTest.php
@@ -69,7 +69,7 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase
             '\Magento\Checkout\Service\V1\Address\Converter', [], [], '', false
         );
 
-        $this->loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
 
         $this->service = new \Magento\Checkout\Service\V1\Address\Billing\WriteService(
             $this->quoteRepositoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php
index 282fb0ba66efa9ab143d07c4dccfb76c480ed597..d8ba19ff325567bbf844d919667fa8d235aea9b0 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/Shipping/WriteServiceTest.php
@@ -71,7 +71,7 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->service = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Address\Shipping\WriteService',
+            'Magento\Checkout\Service\V1\Address\Shipping\WriteService',
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'quoteAddressFactory' => $this->addressFactoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/ValidatorTest.php
index 5c3a5952ef2556491041faca6c5cc318c98a2ad4..52fe4ee058964122bc171a89b05019f99faebaa0 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/ValidatorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Address/ValidatorTest.php
@@ -68,12 +68,12 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->addressDataBuilder = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Data\Cart\AddressBuilder',
+            'Magento\Checkout\Service\V1\Data\Cart\AddressBuilder',
             ['regionBuilder' => $builder]
         );
 
         $this->model = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Address\Validator',
+            'Magento\Checkout\Service\V1\Address\Validator',
             [
                 'quoteAddressFactory' => $this->addressFactoryMock,
                 'customerFactory' => $this->customerFactoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/BuilderTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/BuilderTest.php
index daccd8b4144bb2c7e88fa876ad517b69f3dd37de..04324909f396da348ba73728804ba6cc87a3b9bc 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/BuilderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/BuilderTest.php
@@ -21,7 +21,7 @@ class BuilderTest extends \PHPUnit_Framework_TestCase
     {
         $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->builder = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Data\Cart\PaymentMethod\Builder'
+            'Magento\Checkout\Service\V1\Data\Cart\PaymentMethod\Builder'
         );
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/ConverterTest.php
index 296b8aaf8a04628d368070cc3768397c55048551..9e2c0ea62add40f4d886d29e562b7fd28e303409 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/ConverterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/PaymentMethod/ConverterTest.php
@@ -36,7 +36,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->converter = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Data\Cart\PaymentMethod\Converter',
+            'Magento\Checkout\Service\V1\Data\Cart\PaymentMethod\Converter',
             [
                 'builder' => $this->paymentMethodBuilderMock,
             ]
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php
index 190ed00f085713fce540907fe820ec7fd98dd390..da0cdc677b33c9a8c1247465b2f2620954726e85 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/ReadServiceTest.php
@@ -60,7 +60,7 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
         ];
         $this->quoteMock = $this->getMock('\Magento\Sales\Model\Quote', $methods, [], '', false);
         $this->quoteCollectionMock = $objectManager->getCollectionMock(
-            '\Magento\Sales\Model\Resource\Quote\Collection', [$this->quoteMock]);
+            'Magento\Sales\Model\Resource\Quote\Collection', [$this->quoteMock]);
         $this->searchResultsBuilderMock =
             $this->getMock('\Magento\Checkout\Service\V1\Data\CartSearchResultsBuilder', [], [], '', false);
         $this->cartMapperMock = $this->getMock('\Magento\Checkout\Service\V1\Data\CartMapper', ['map'], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php
index edee9277ac423f4386e1d7a414c372f3f1a16ddf..5e683c744345a52339481e3838acf3b865ea7c2a 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Cart/WriteServiceTest.php
@@ -104,7 +104,7 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->service = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Cart\WriteService',
+            'Magento\Checkout\Service\V1\Cart\WriteService',
             [
                 'storeManager' => $this->storeManagerMock,
                 'customerRepository' => $this->customerRepositoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php
index 86ea3f35499b69217bab5ccf160a87a72da699e5..18f1afad761b9b02c3060ced5545651b5d06bc9e 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Coupon/ReadServiceTest.php
@@ -33,7 +33,7 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
             '\Magento\Checkout\Service\V1\Data\Cart\CouponBuilder', [], [], '', false
         );
         $this->service = $objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Coupon\ReadService',
+            'Magento\Checkout\Service\V1\Coupon\ReadService',
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'couponBuilder' => $this->couponBuilderMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Data/PaymentMethod/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Data/PaymentMethod/ConverterTest.php
index 7069ba299ea581fdc2cb12e3f761e22fd0ca796f..58f49fce1290ebe463662f5bfaf0905b61d182c8 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Data/PaymentMethod/ConverterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/Data/PaymentMethod/ConverterTest.php
@@ -32,7 +32,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->converter = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\Data\PaymentMethod\Converter',
+            'Magento\Checkout\Service\V1\Data\PaymentMethod\Converter',
             [
                 'builder' => $this->paymentMethodBuilderMock,
             ]
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php
index 7fb960654ef25cddc47fa9a11e48bb9c56cf2cac..7bfdd2524ba758f2bfd0efb09f6edc390b9168cf 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/ReadServiceTest.php
@@ -50,7 +50,7 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
         $this->methodListMock = $this->getMock('\Magento\Payment\Model\MethodList', [], [], '', false);
 
         $this->service = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\PaymentMethod\ReadService',
+            'Magento\Checkout\Service\V1\PaymentMethod\ReadService',
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'quoteMethodConverter' => $this->quoteMethodConverterMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php
index 7a07b8c8aad863f34a9d712a81899de567406642..918124800a2b4b43c099c87ca42cdad1b731b87a 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/PaymentMethod/WriteServiceTest.php
@@ -49,7 +49,7 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase
         $this->validatorMock = $this->getMock('\Magento\Payment\Model\Checks\ZeroTotal', [], [], '', false);
 
         $this->service = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\PaymentMethod\WriteService',
+            'Magento\Checkout\Service\V1\PaymentMethod\WriteService',
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'paymentMethodBuilder' => $this->paymentMethodBuilderMock,
diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php
index cfae35ef94aaf51676a03d6a369bcb0309746e11..d48c14f27b7d3f02286270ee84360e5a553de0fa 100644
--- a/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Checkout/Service/V1/ShippingMethod/ReadServiceTest.php
@@ -96,7 +96,7 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->service = $this->objectManager->getObject(
-            '\Magento\Checkout\Service\V1\ShippingMethod\ReadService',
+            'Magento\Checkout\Service\V1\ShippingMethod\ReadService',
             [
                 'quoteRepository' => $this->quoteRepositoryMock,
                 'methodBuilder' => $this->methodBuilderMock,
diff --git a/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php b/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php
index a775fd23cf4c1828b95bbb44dfc780b9f7d80529..c7b36ca7edad0c5ffe8fcc91a6a9d4bd7ef252b6 100644
--- a/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php
+++ b/dev/tests/unit/testsuite/Magento/CheckoutAgreements/Model/AgreementTest.php
@@ -14,7 +14,7 @@ class AgreementTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->model = $this->objectManager->getObject('\Magento\CheckoutAgreements\Model\Agreement');
+        $this->model = $this->objectManager->getObject('Magento\CheckoutAgreements\Model\Agreement');
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/PageCriteriaMapperTest.php b/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/PageCriteriaMapperTest.php
index 1affb8ae653b180b01aeaca786f5d07cdd4a52b0..1db747a91061da43a787a53e4d307fa01f794256 100644
--- a/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/PageCriteriaMapperTest.php
+++ b/dev/tests/unit/testsuite/Magento/Cms/Model/Resource/PageCriteriaMapperTest.php
@@ -10,7 +10,7 @@ namespace Magento\Cms\Model\Resource;
 class PageCriteriaMapperTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -46,13 +46,7 @@ class PageCriteriaMapperTest extends \PHPUnit_Framework_TestCase
      */
     protected function setUp()
     {
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMockForAbstractClass(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
index 2f072bd8810f72ec169d3962b3d80c40dce37782..7f282cceff00a384226fc73265059804c0728130 100644
--- a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
@@ -51,7 +51,7 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
         $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $this->_typeConfigurableFactory = $this->getMock(
             'Magento\ConfigurableProduct\Model\Resource\Product\Type\ConfigurableFactory',
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/Directory/DatabaseTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/Directory/DatabaseTest.php
index 3e0af8d3cc2993df8e57d8c3f5eedb5aeb9abcdd..24c78c03786b39633b890ca187fc14923c48ca2e 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/Directory/DatabaseTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/Directory/DatabaseTest.php
@@ -55,7 +55,7 @@ class DatabaseTest extends \PHPUnit_Framework_TestCase
     protected $resourceDirectoryDatabaseMock;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $loggerMock;
 
@@ -106,7 +106,7 @@ class DatabaseTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->directoryFactoryMock->expects(
             $this->any()
@@ -175,7 +175,7 @@ class DatabaseTest extends \PHPUnit_Framework_TestCase
     {
         $this->directoryMock->expects($this->any())->method('getParentId')->will($this->returnValue(null));
 
-        $this->loggerMock->expects($this->any())->method('logException');
+        $this->loggerMock->expects($this->any())->method('critical');
 
         $this->directoryDatabase->importDirectories([]);
     }
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/MediaTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/MediaTest.php
index 86d283fc25bd1060e5cd913e20876f7e4696c1b5..ae0ed046c2bae69a9ec8c0fd0b4e87f5f9bdd128 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/MediaTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/File/Storage/MediaTest.php
@@ -36,7 +36,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->_loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->_loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->_storageHelperMock = $this->getMock(
             'Magento\Core\Helper\File\Storage\Database',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/Layout/MergeTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/Layout/MergeTest.php
index 1b0e8eaa4dea6079cf1c9da12ec7c372859bb8c0..028bec513f8fba31956b3d2234c2ec504fadfdca 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/Layout/MergeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/Layout/MergeTest.php
@@ -79,7 +79,7 @@ class MergeTest extends \PHPUnit_Framework_TestCase
 
         $this->_appState = $this->getMock('Magento\Framework\App\State', [], [], '', false);
 
-        $this->_logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->_logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->_layoutValidator = $this->getMock(
             'Magento\Core\Model\Layout\Update\Validator',
@@ -294,12 +294,8 @@ class MergeTest extends \PHPUnit_Framework_TestCase
     public function testGetFileLayoutUpdatesXml()
     {
         $errorString = "Theme layout update file '" . __DIR__ . "/_files/layout/file_wrong.xml' is not valid.";
-        $this->_logger->expects($this->atLeastOnce())->method('log')
-            ->with(
-                $this->stringStartsWith($errorString),
-                \Zend_Log::ERR,
-                \Magento\Framework\Logger::LOGGER_SYSTEM
-            );
+        $this->_logger->expects($this->atLeastOnce())->method('info')
+            ->with($this->stringStartsWith($errorString));
 
         $actualXml = $this->_model->getFileLayoutUpdatesXml();
         $this->assertXmlStringEqualsXmlFile(__DIR__ . '/_files/merged.xml', $actualXml->asNiceXml());
@@ -406,11 +402,8 @@ class MergeTest extends \PHPUnit_Framework_TestCase
         $messages = $this->_layoutValidator->getMessages();
 
         // Testing error message is logged with logger
-        $this->_logger->expects($this->once())->method('log')
-            ->with(
-                'Cache file with merged layout: ' . $cacheId . ': ' . array_shift($messages),
-                \Zend_Log::ERR
-            );
+        $this->_logger->expects($this->once())->method('info')
+            ->with('Cache file with merged layout: ' . $cacheId . ': ' . array_shift($messages));
 
         $this->_model->load();
     }
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/File/Storage/FileTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/File/Storage/FileTest.php
index 343573b5df69f66ff5f65fbcabb1f21ca7e887d4..5f61a0eddc9f8aba300101886499f5e70c469acf 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/File/Storage/FileTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/File/Storage/FileTest.php
@@ -36,7 +36,7 @@ class FileTest extends \PHPUnit_Framework_TestCase
      */
     protected function setUp()
     {
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->filesystemMock = $this->getMock(
             'Magento\Framework\Filesystem',
             ['getDirectoryRead'],
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Link/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Link/CollectionTest.php
index 85a97321f602873e4000501d8a6c6f94a0e8e0a8..d606ae998b9f3695e12f38eb8cb547bca5fe80c3 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Link/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Link/CollectionTest.php
@@ -28,7 +28,7 @@ class CollectionTest extends \Magento\Core\Model\Resource\Layout\AbstractTestCas
 
         return new \Magento\Core\Model\Resource\Layout\Link\Collection(
             $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false),
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMockForAbstractClass('Magento\Framework\Data\Collection\Db\FetchStrategyInterface'),
             $eventManager,
             $this->getMock('Magento\Framework\Stdlib\DateTime', null, [], '', true),
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Update/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Update/CollectionTest.php
index 06ae56f3b048fe2955a50d1bd66dd92f224af8ce..34d7145aafd3c785e471504355f0701f2df346a4 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Update/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/Resource/Layout/Update/CollectionTest.php
@@ -18,7 +18,7 @@ class CollectionTest extends \Magento\Core\Model\Resource\Layout\AbstractTestCas
 
         return new \Magento\Core\Model\Resource\Layout\Update\Collection(
             $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false),
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMockForAbstractClass('Magento\Framework\Data\Collection\Db\FetchStrategyInterface'),
             $eventManager,
             $this->getMock('Magento\Framework\Stdlib\DateTime', null, [], '', true),
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php b/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
index 3ff772d19f703994eb1b506eead8faa825c7beac..0cce2cb3e3fc55a7112d7fd7cf03b7e4cc9ad4ab 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/AccountTest.php
@@ -100,7 +100,7 @@ class AccountTest extends \PHPUnit_Framework_TestCase
         $layoutMock->expects($this->at(0))->method('createBlock')
             ->with('Magento\Customer\Block\Adminhtml\Edit\Renderer\Attribute\Group')
             ->will($this->returnValue(
-                $this->objectManagerHelper->getObject('\Magento\Customer\Block\Adminhtml\Edit\Renderer\Attribute\Group')
+                $this->objectManagerHelper->getObject('Magento\Customer\Block\Adminhtml\Edit\Renderer\Attribute\Group')
             ));
         $layoutMock->expects($this->at(1))->method('createBlock')
             ->with('Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset\Element')
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Block/NewsletterTest.php b/dev/tests/unit/testsuite/Magento/Customer/Block/NewsletterTest.php
index 4ddb6f8c5c7ba7bef9991f560f25dd2d88d13009..728853623ad04664ee775eb141f95ef78605b5dd 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Block/NewsletterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Block/NewsletterTest.php
@@ -20,7 +20,7 @@ class NewsletterTest extends \PHPUnit_Framework_TestCase
     {
         $this->urlBuilder = $this->getMock('\Magento\Framework\UrlInterface');
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->block = $helper->getObject('\Magento\Customer\Block\Newsletter', ['urlBuilder' => $this->urlBuilder]);
+        $this->block = $helper->getObject('Magento\Customer\Block\Newsletter', ['urlBuilder' => $this->urlBuilder]);
     }
 
     public function testGetAction()
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Block/Widget/DobTest.php b/dev/tests/unit/testsuite/Magento/Customer/Block/Widget/DobTest.php
index 5e1faeb65fc3c7d5cebe817002fbf234cbffcd3f..63e82abc9ee48eec3836690159f88c7df1dc6d8d 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Block/Widget/DobTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Block/Widget/DobTest.php
@@ -62,13 +62,13 @@ class DobTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $locale = $objectManager->getObject(
-            '\Magento\Framework\Locale',
+            'Magento\Framework\Locale',
             ['locale' => \Magento\Framework\Locale\ResolverInterface::DEFAULT_LOCALE]
         );
         $localeResolver = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
         $localeResolver->expects($this->any())->method('getLocale')->will($this->returnValue($locale));
         $timezone = $objectManager->getObject(
-            '\Magento\Framework\Stdlib\DateTime\Timezone',
+            'Magento\Framework\Stdlib\DateTime\Timezone',
             ['localeResolver' => $localeResolver]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Attribute/Data/PostcodeTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Attribute/Data/PostcodeTest.php
index d5b34e20715f846ce8670d56bf29418da89dfde7..fd40eb5504a8f80007ed44b84c51acca8125ab64 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Attribute/Data/PostcodeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Attribute/Data/PostcodeTest.php
@@ -31,7 +31,7 @@ class PostcodeTest extends \PHPUnit_Framework_TestCase
     private $localeResolverMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     private $loggerMock;
 
@@ -41,8 +41,7 @@ class PostcodeTest extends \PHPUnit_Framework_TestCase
             ->getMock();
         $this->localeResolverMock = $this->getMockBuilder('Magento\Framework\Locale\ResolverInterface')
             ->getMock();
-        $this->loggerMock = $this->getMockBuilder('Magento\Framework\Logger')
-            ->disableOriginalConstructor()
+        $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')
             ->getMock();
         $this->directoryHelperMock = $this->getMockBuilder('Magento\Directory\Helper\Data')
             ->disableOriginalConstructor()
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php
index 21d44a8283eb08a9051469426ac3711a2956dea9..15a2fb85938aa51362a0b24b8a30cd11448f3867 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php
@@ -13,8 +13,8 @@ class BillingTest extends \PHPUnit_Framework_TestCase
 
     public function setUp()
     {
-        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
-        /** @var \Magento\Framework\Logger $logger */
+        $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+        /** @var \Psr\Log\LoggerInterface $logger */
         $this->testable = new Billing($logger);
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php
index 463632cb97d94539929f0e0197277235c4ca64c9..c4dcd2f89ae720fb7017294b8f8b0af5c6e20acd 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php
@@ -14,8 +14,8 @@ class ShippingTest extends \PHPUnit_Framework_TestCase
 
     public function setUp()
     {
-        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
-        /** @var \Magento\Framework\Logger $logger */
+        $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+        /** @var \Psr\Log\LoggerInterface $logger */
         $this->testable = new Shipping($logger);
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractDataTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractDataTest.php
index 41b751c72a04361e539261915184b81d284e36e0..937392319dc76ec1e3648b76a0243fb9d8fb2bf9 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractDataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractDataTest.php
@@ -19,7 +19,7 @@ class AbstractDataTest extends \PHPUnit_Framework_TestCase
     /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Locale\ResolverInterface */
     protected $_localeResolverMock;
 
-    /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Logger */
+    /** @var \PHPUnit_Framework_MockObject_MockObject | \Psr\Log\LoggerInterface */
     protected $_loggerMock;
 
     /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Api\Data\AttributeMetadataInterface */
@@ -42,7 +42,7 @@ class AbstractDataTest extends \PHPUnit_Framework_TestCase
         $this->_localeResolverMock = $this->getMockBuilder(
             'Magento\Framework\Locale\ResolverInterface'
         )->disableOriginalConstructor()->getMock();
-        $this->_loggerMock = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        $this->_loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
         $this->_attributeMock = $this->getMock('Magento\Customer\Api\Data\AttributeMetadataInterface');
         $this->_value = 'VALUE';
         $this->_entityTypeCode = 'ENTITY_TYPE_CODE';
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractFormTestCase.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractFormTestCase.php
index 827aa69df61dd924defc72eb2d666cc8a17e8908..eea536eb7e0a85594042f6e03518c706de98abfa 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractFormTestCase.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Metadata/Form/AbstractFormTestCase.php
@@ -13,7 +13,7 @@ abstract class AbstractFormTestCase extends \PHPUnit_Framework_TestCase
     /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Locale\ResolverInterface */
     protected $localeResolverMock;
 
-    /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Logger */
+    /** @var \PHPUnit_Framework_MockObject_MockObject | \Psr\Log\LoggerInterface */
     protected $loggerMock;
 
     /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Api\Data\AttributeMetadataInterface */
@@ -23,7 +23,7 @@ abstract class AbstractFormTestCase extends \PHPUnit_Framework_TestCase
     {
         $this->localeMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\TimezoneInterface')->getMock();
         $this->localeResolverMock = $this->getMockBuilder('Magento\Framework\Locale\ResolverInterface')->getMock();
-        $this->loggerMock = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
         $this->attributeMetadataMock = $this->getMock('Magento\Customer\Api\Data\AttributeMetadataInterface');
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/Group/Grid/ServiceCollectionTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/Group/Grid/ServiceCollectionTest.php
index 71e1db6d481d05da539b3ad0f4f7198136a6ce20..f3ed61dc74af352f36e45ef43a58175a8ae722df 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/Group/Grid/ServiceCollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/Group/Grid/ServiceCollectionTest.php
@@ -36,7 +36,7 @@ class ServiceCollectionTest extends \PHPUnit_Framework_TestCase
     public function setUp()
     {
         $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->filterBuilder = $this->objectManager->getObject('\Magento\Framework\Api\FilterBuilder');
+        $this->filterBuilder = $this->objectManager->getObject('Magento\Framework\Api\FilterBuilder');
         $filterGroupBuilder = $this->objectManager
             ->getObject('Magento\Framework\Api\Search\FilterGroupBuilder');
         /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchBuilder */
@@ -45,7 +45,7 @@ class ServiceCollectionTest extends \PHPUnit_Framework_TestCase
             ['filterGroupBuilder' => $filterGroupBuilder]
         );
         $this->sortOrderBuilder = $this->objectManager->getObject(
-            '\Magento\Framework\Api\SortOrderBuilder'
+            'Magento\Framework\Api\SortOrderBuilder'
         );
         $this->groupRepositoryMock = $this->getMockBuilder('\Magento\Customer\Api\GroupRepositoryInterface')
             ->getMock();
diff --git a/dev/tests/unit/testsuite/Magento/Directory/Model/PriceCurrencyTest.php b/dev/tests/unit/testsuite/Magento/Directory/Model/PriceCurrencyTest.php
index 6b644e2703ffacfe07e21aafac40377e71d8294a..52490c8b7964f7aec745cce08131fc62b7576033 100644
--- a/dev/tests/unit/testsuite/Magento/Directory/Model/PriceCurrencyTest.php
+++ b/dev/tests/unit/testsuite/Magento/Directory/Model/PriceCurrencyTest.php
@@ -33,8 +33,7 @@ class PriceCurrencyTest extends \PHPUnit_Framework_TestCase
             ->setMethods(['create'])
             ->getMock();
 
-        $this->logger = $this->getMockBuilder('Magento\Framework\Logger')
-            ->disableOriginalConstructor()
+        $this->logger = $this->getMockBuilder('Psr\Log\LoggerInterface')
             ->getMock();
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
diff --git a/dev/tests/unit/testsuite/Magento/Directory/Model/Resource/Country/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Directory/Model/Resource/Country/CollectionTest.php
index 0d46c4bec543a24c14f8dd8c3866a3c0a19b0047..00158413afe0ded2914cf998b32753965f11ba0f 100644
--- a/dev/tests/unit/testsuite/Magento/Directory/Model/Resource/Country/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Directory/Model/Resource/Country/CollectionTest.php
@@ -35,7 +35,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
         $fetchStrategy = $this->getMockForAbstractClass('Magento\Framework\Data\Collection\Db\FetchStrategyInterface');
         $entityFactory = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
         $scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $countryFactory = $this->getMock(
             'Magento\Directory\Model\Resource\CountryFactory',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Downloadable/Model/Product/TypeTest.php b/dev/tests/unit/testsuite/Magento/Downloadable/Model/Product/TypeTest.php
index c5ac347e6e3224c79a6a2082173446752ee7fd34..2542ded81899faf4f9abf36f869cda02ea32d784 100644
--- a/dev/tests/unit/testsuite/Magento/Downloadable/Model/Product/TypeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Downloadable/Model/Product/TypeTest.php
@@ -26,7 +26,7 @@ class TypeTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
         $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $sampleResFactory = $this->getMock('Magento\Downloadable\Model\Resource\SampleFactory', [], [], '', false);
         $linkResource = $this->getMock('Magento\Downloadable\Model\Resource\Link', [], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/AbstractDataTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/AbstractDataTest.php
index 01669f34e3def192c36ba6b5159683f71b75312b..f1d427f3744bbec0b0e790263983b5de0cf671ce 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/AbstractDataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/AbstractDataTest.php
@@ -14,7 +14,7 @@ class AbstractDataTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
         $stringMock = $this->getMock('\Magento\Framework\Stdlib\String', [], [], '', false);
 
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/BooleanTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/BooleanTest.php
index 6b5d884332806144995305cb52dc1fb7fd2d5c65..0c8ead39311addc41fb80f2241ac553d78872653 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/BooleanTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/BooleanTest.php
@@ -14,7 +14,7 @@ class BooleanTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
 
         $this->model = new Boolean($timezoneMock, $loggerMock, $localeResolverMock);
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/DateTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/DateTest.php
index 4932899f0555262343ff87ed5555519bd7a6e0d1..6bb94af2800ed2b5cf6e0629d3b5a8d93d82173b 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/DateTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/DateTest.php
@@ -19,7 +19,7 @@ class DateTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
 
         $this->model = new Date($this->timezoneMock, $loggerMock, $localeResolverMock);
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/FileTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/FileTest.php
index 70370559083bf15c47edf4cc1155fccd28051445..1560e4e30485577ba6dba08d5ae9ef7b95a5ad38 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/FileTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/FileTest.php
@@ -24,7 +24,7 @@ class FileTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
         $this->urlEncoder = $this->getMock('Magento\Framework\Url\EncoderInterface', [], [], '', false);
         $this->fileValidatorMock = $this->getMock(
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/ImageTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/ImageTest.php
index 59cb2a0d1475e4fe2107779fb0a894cb2ad51d0c..626e8b99683767884560bd0257ad5ae52064318b 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/ImageTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/ImageTest.php
@@ -14,7 +14,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
         $urlEncoder = $this->getMock('Magento\Framework\Url\EncoderInterface', [], [], '', false);
         $fileValidatorMock = $this->getMock(
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultilineTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultilineTest.php
index 0e6e1e1f20fd8a09ed9d5dac285be83750d4e55e..7871eef64e54226e99a12c1296e44c38d4a6ba81 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultilineTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultilineTest.php
@@ -19,7 +19,7 @@ class MultilineTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
         $this->stringMock = $this->getMock('\Magento\Framework\Stdlib\String', [], [], '', false);
 
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultiselectTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultiselectTest.php
index 6304d8fb153878aafb128e20b6b13ade199a07b2..969ebfcfd5da6d70eef84de1093a28ef754a02ec 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultiselectTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/MultiselectTest.php
@@ -14,7 +14,7 @@ class MultiselectTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
 
         $this->model = new Multiselect($timezoneMock, $loggerMock, $localeResolverMock);
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/SelectTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/SelectTest.php
index 5500ddd0bb7e58caf5c630c43cbb9cd8c5dbfa29..611c5c81d21583c52d45a9886db5c333b1c2a6ca 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/SelectTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/SelectTest.php
@@ -14,7 +14,7 @@ class SelectTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $timezoneMock = $this->getMock('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
-        $loggerMock = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $localeResolverMock = $this->getMock('\Magento\Framework\Locale\ResolverInterface');
 
         $this->model = new Select($timezoneMock, $loggerMock, $localeResolverMock);
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/TextTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/TextTest.php
index bd6504e7eea1e4ad7c8c5fab7997b1ad25ef6410..8b02bb74601d1dbed160bb75ff9940bb7c0f32fe 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/TextTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/Data/TextTest.php
@@ -29,7 +29,7 @@ class TextTest extends \PHPUnit_Framework_TestCase
             false,
             false
         );
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false, false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $helper = $this->getMock('Magento\Framework\Stdlib\String', [], [], '', false, false);
 
         $attributeData = [
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/GroupRepositoryTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/GroupRepositoryTest.php
index 49c27d38b7581d3a08a1bba2a424909be81ab8e6..b177b478a5f0dfee59daa01479877b14829a4a78 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/GroupRepositoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Attribute/GroupRepositoryTest.php
@@ -70,7 +70,7 @@ class GroupRepositoryTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\Eav\Model\Attribute\GroupRepository',
+            'Magento\Eav\Model\Attribute\GroupRepository',
             [
                 'groupResource' => $this->groupResourceMock,
                 'groupListFactory' => $this->groupListFactoryMock,
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Backend/ArrayTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Backend/ArrayTest.php
index 00cc2d8ec139b9871b36ce282c5cdbd3142269f6..6d83b5cf5687097219fa74709a229d5f977cf20a 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Backend/ArrayTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Attribute/Backend/ArrayTest.php
@@ -25,7 +25,7 @@ class ArrayTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->_model = new \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend($logger);
         $this->_model->setAttribute($this->_attribute);
     }
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Collection/AbstractCollectionTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Collection/AbstractCollectionTest.php
index 643be759694cbccf4f828b71426cdea9c7f29b33..8c2fbd95ed9c58926d0ce8f8e38188d2d12a69eb 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Collection/AbstractCollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Entity/Collection/AbstractCollectionTest.php
@@ -17,7 +17,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     protected $coreEntityFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -59,7 +59,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     public function setUp()
     {
         $this->coreEntityFactoryMock = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php
index 0d712466ff20d64a1c74efc14246dff76a24437c..b7bfd64d583a7891caba721e9b891c1690cb4228 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php
@@ -17,7 +17,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected $entityFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -64,7 +64,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->entityFactoryMock = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock('Magento\Framework\Data\Collection\Db\FetchStrategyInterface');
         $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
 
@@ -164,7 +164,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     public function testInitSelect($column, $value, $expected)
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->model = $helper->getObject('\Magento\Customer\Model\Resource\Attribute\Collection',
+        $this->model = $helper->getObject('Magento\Customer\Model\Resource\Attribute\Collection',
             [
                 'entityFactory' => $this->entityFactoryMock,
                 'logger' => $this->loggerMock,
diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Entity/Attribute/Option/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Entity/Attribute/Option/CollectionTest.php
index 7d2313e46b0aa399c7b2dce7b6938088b1c27187..5e27db60b517fc9189456d681734fb83816d7da5 100644
--- a/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Entity/Attribute/Option/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Entity/Attribute/Option/CollectionTest.php
@@ -17,7 +17,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected $entityFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -59,7 +59,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->entityFactoryMock = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Email/Block/Adminhtml/Template/EditTest.php b/dev/tests/unit/testsuite/Magento/Email/Block/Adminhtml/Template/EditTest.php
index 8b54b0509e57637d35b9848700b96b83b5cccac2..12105ab2f5527c33cba754c69461d1bb1f664a59 100644
--- a/dev/tests/unit/testsuite/Magento/Email/Block/Adminhtml/Template/EditTest.php
+++ b/dev/tests/unit/testsuite/Magento/Email/Block/Adminhtml/Template/EditTest.php
@@ -52,7 +52,7 @@ class EditTest extends \PHPUnit_Framework_TestCase
         $menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
         $menuItemMock = $this->getMock('Magento\Backend\Model\Menu\Item', [], [], '', false, false);
         $urlBuilder = $this->getMock('Magento\Backend\Model\Url', [], [], '', false, false);
diff --git a/dev/tests/unit/testsuite/Magento/Fedex/Model/CarrierTest.php b/dev/tests/unit/testsuite/Magento/Fedex/Model/CarrierTest.php
index c770c8f10b3a79bb3d080eae296a18750bccf290..b02a6e9a733685d454e9d4c7d3a13867ac427062 100644
--- a/dev/tests/unit/testsuite/Magento/Fedex/Model/CarrierTest.php
+++ b/dev/tests/unit/testsuite/Magento/Fedex/Model/CarrierTest.php
@@ -77,7 +77,7 @@ class CarrierTest extends \PHPUnit_Framework_TestCase
                 'scopeConfig' => $scopeConfig,
                 'rateErrorFactory' =>
                     $this->getMock('Magento\Sales\Model\Quote\Address\RateResult\ErrorFactory', [], [], '', false),
-                'logAdapterFactory' => $this->getMock('Magento\Framework\Logger\AdapterFactory', [], [], '', false),
+                'logger' => $this->getMock('Psr\Log\LoggerInterface'),
                 'xmlElFactory' => $this->getMock('Magento\Shipping\Model\Simplexml\ElementFactory', [], [], '', false),
                 'rateFactory' => $rateFactory,
                 'rateMethodFactory' => $rateMethodFactory,
@@ -91,7 +91,6 @@ class CarrierTest extends \PHPUnit_Framework_TestCase
                 'currencyFactory' => $this->getMock('Magento\Directory\Model\CurrencyFactory', [], [], '', false),
                 'directoryData' => $this->getMock('Magento\Directory\Helper\Data', [], [], '', false),
                 'stockRegistry' => $this->getMock('Magento\CatalogInventory\Model\StockRegistry', [], [], '', false),
-                'logger' => $this->getMock('Magento\Framework\Logger', [], [], '', false),
                 'storeManager' => $storeManager,
                 'configReader' => $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false),
                 'productCollectionFactory' =>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Api/Data/AttributeValueTest.php b/dev/tests/unit/testsuite/Magento/Framework/Api/Data/AttributeValueTest.php
index f9639ea5425262002b29cd5fe6e5b83f06e3314f..fd20df2184fb527711ede7a342e8a9bf337228f4 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Api/Data/AttributeValueTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Api/Data/AttributeValueTest.php
@@ -21,7 +21,7 @@ class AttributeValueTest extends \PHPUnit_Framework_TestCase
     public function testConstructorAndGettersWithString()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $attributeBuilder = $helper->getObject('\Magento\Framework\Api\AttributeDataBuilder')
+        $attributeBuilder = $helper->getObject('Magento\Framework\Api\AttributeDataBuilder')
             ->setAttributeCode(self::ATTRIBUTE_CODE)
             ->setValue(self::STRING_VALUE);
         $attribute = new AttributeValue($attributeBuilder);
@@ -33,7 +33,7 @@ class AttributeValueTest extends \PHPUnit_Framework_TestCase
     public function testConstructorAndGettersWithInteger()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $attributeBuilder = $helper->getObject('\Magento\Framework\Api\AttributeDataBuilder')
+        $attributeBuilder = $helper->getObject('Magento\Framework\Api\AttributeDataBuilder')
             ->setAttributeCode(self::ATTRIBUTE_CODE)
             ->setValue(self::INTEGER_VALUE);
         $attribute = new AttributeValue($attributeBuilder);
@@ -45,7 +45,7 @@ class AttributeValueTest extends \PHPUnit_Framework_TestCase
     public function testConstructorAndGettersWithFloat()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $attributeBuilder = $helper->getObject('\Magento\Framework\Api\AttributeDataBuilder')
+        $attributeBuilder = $helper->getObject('Magento\Framework\Api\AttributeDataBuilder')
             ->setAttributeCode(self::ATTRIBUTE_CODE)
             ->setValue(self::FLOAT_VALUE);
         $attribute = new AttributeValue($attributeBuilder);
@@ -57,7 +57,7 @@ class AttributeValueTest extends \PHPUnit_Framework_TestCase
     public function testConstructorAndGettersWithBoolean()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $attributeBuilder = $helper->getObject('\Magento\Framework\Api\AttributeDataBuilder')
+        $attributeBuilder = $helper->getObject('Magento\Framework\Api\AttributeDataBuilder')
             ->setAttributeCode(self::ATTRIBUTE_CODE)
             ->setValue(self::BOOLEAN_VALUE);
         $attribute = new AttributeValue($attributeBuilder);
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/BootstrapTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/BootstrapTest.php
index 11b5ff8d5ea3ae03237e34a6a875c2d48e2d205b..986ad6a02af5632186c871a9a92b8f088548a648 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/App/BootstrapTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/BootstrapTest.php
@@ -25,7 +25,7 @@ class BootstrapTest extends \PHPUnit_Framework_TestCase
     protected $objectManager;
 
     /**
-     * @var \Magento\Framework\Logger | \PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface | \PHPUnit_Framework_MockObject_MockObject
      */
     protected $logger;
 
@@ -62,7 +62,7 @@ class BootstrapTest extends \PHPUnit_Framework_TestCase
         $this->maintenanceMode = $this->getMock('Magento\Framework\App\MaintenanceMode', ['isOn'], [], '', false);
         $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
 
-        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->deploymentConfig = $this->getMock('Magento\Framework\App\DeploymentConfig', [], [], '', false);
 
@@ -71,7 +71,7 @@ class BootstrapTest extends \PHPUnit_Framework_TestCase
             ['Magento\Framework\App\MaintenanceMode', $this->maintenanceMode],
             ['Magento\Framework\Filesystem', $filesystem],
             ['Magento\Framework\App\DeploymentConfig', $this->deploymentConfig],
-            ['Magento\Framework\Logger', $this->logger],
+            ['Psr\Log\LoggerInterface', $this->logger],
         ];
 
         $this->objectManager->expects($this->any())->method('get')
diff --git a/dev/tests/unit/testsuite/Magento/Framework/DB/AbstractMapperTest.php b/dev/tests/unit/testsuite/Magento/Framework/DB/AbstractMapperTest.php
index 9a97d863332b53173db24ce45d4126b2891cf7b0..7ccd46efefa567e3f9a8de6a69d687ed4c4b3b87 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/DB/AbstractMapperTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/DB/AbstractMapperTest.php
@@ -25,7 +25,7 @@ class AbstractMapperTest extends \PHPUnit_Framework_TestCase
     protected $selectMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -81,13 +81,7 @@ class AbstractMapperTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMockForAbstractClass(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Framework/DB/Logger/FileTest.php b/dev/tests/unit/testsuite/Magento/Framework/DB/Logger/FileTest.php
index 63c684524727ba6a91182a4eece89ae325e32981..e883b622eb3683e495e40711ca04ef7f41faba92 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/DB/Logger/FileTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/DB/Logger/FileTest.php
@@ -128,7 +128,7 @@ class FileTest extends \PHPUnit_Framework_TestCase
         $this->object->logStats('unknown', 'SELECT something');
     }
 
-    public function testLogException()
+    public function testcritical()
     {
         $exception = new \Exception('error message');
         $expected = "%aEXCEPTION%a'Exception'%a'error message'%a";
@@ -137,6 +137,6 @@ class FileTest extends \PHPUnit_Framework_TestCase
             ->method('write')
             ->with($this->matches($expected));
 
-        $this->object->logException($exception);
+        $this->object->critical($exception);
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/DB/QueryTest.php b/dev/tests/unit/testsuite/Magento/Framework/DB/QueryTest.php
index 799e194e822e0dcecee30c71d269c26411223f49..fa8981c85e39c3737b307f9972f1ac226f3b5faa 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/DB/QueryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/DB/QueryTest.php
@@ -30,7 +30,7 @@ class QueryTest extends \PHPUnit_Framework_TestCase
     protected $fetchStmtMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -85,13 +85,7 @@ class QueryTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMockForAbstractClass(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Data/AbstractCriteriaTest.php b/dev/tests/unit/testsuite/Magento/Framework/Data/AbstractCriteriaTest.php
index 4751c65c29d2b763c3a55e7d10295fab129957b0..55b3d94536d1f97b9b7efd4264eaac7fc3f1c7fc 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Data/AbstractCriteriaTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Data/AbstractCriteriaTest.php
@@ -24,7 +24,7 @@ class AbstractCriteriaTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->criteria = $objectManager->getObject('\Magento\Framework\Data\Criteria\Sample');
+        $this->criteria = $objectManager->getObject('Magento\Framework\Data\Criteria\Sample');
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Data/Collection/DbTest.php b/dev/tests/unit/testsuite/Magento/Framework/Data/Collection/DbTest.php
index 526254a8ddba1fbceaa715df738fe1ffed87d04f..34dbe81ac5930567eff4576bf1e8e6417bd4ca6d 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Data/Collection/DbTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Data/Collection/DbTest.php
@@ -12,7 +12,7 @@ class DbTest extends \PHPUnit_Framework_TestCase
     protected $collection;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -34,7 +34,7 @@ class DbTest extends \PHPUnit_Framework_TestCase
         $this->entityFactoryMock = $this->getMock(
             'Magento\Core\Model\EntityFactory', ['create'], [], '', false
         );
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->collection = new \Magento\Framework\Data\Collection\Db(
             $this->entityFactoryMock,
             $this->loggerMock,
@@ -306,7 +306,7 @@ class DbTest extends \PHPUnit_Framework_TestCase
     public function testPrintLogQueryLogging($logQuery, $logFlag, $expectedCalls)
     {
         $this->collection->setFlag('log_query', $logFlag);
-        $this->loggerMock->expects($this->exactly($expectedCalls))->method('log');
+        $this->loggerMock->expects($this->exactly($expectedCalls))->method('info');
         $this->collection->printLogQuery(false, $logQuery, 'some_query');
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Framework/HTTP/HeaderTest.php b/dev/tests/unit/testsuite/Magento/Framework/HTTP/HeaderTest.php
index 21079262a0fd9b52e255720ccf311ced7461434d..05efc158f0a99165d5879362dc478f7fd407725c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/HTTP/HeaderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/HTTP/HeaderTest.php
@@ -56,7 +56,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
         $this->_prepareCleanString($clean);
 
         $headerObject = $this->_objectManager->getObject(
-            '\Magento\Framework\HTTP\Header',
+            'Magento\Framework\HTTP\Header',
             ['httpRequest' => $this->_request, 'converter' => $this->_converter]
         );
 
@@ -138,7 +138,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase
         $this->_prepareCleanString($clean);
 
         $headerObject = $this->_objectManager->getObject(
-            '\Magento\Framework\HTTP\Header',
+            'Magento\Framework\HTTP\Header',
             ['httpRequest' => $this->_request, 'converter' => $this->_converter]
         );
 
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Image/Adapter/Gd2Test.php b/dev/tests/unit/testsuite/Magento/Framework/Image/Adapter/Gd2Test.php
index 4ac70fbf71dd7775ce52f4081a6462de08f2aa59..9136cc70df5b474b533e8f840b07712a8cd2628f 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Image/Adapter/Gd2Test.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Image/Adapter/Gd2Test.php
@@ -89,7 +89,7 @@ class Gd2Test extends \PHPUnit_Framework_TestCase
     public function setUp()
     {
         $this->objectManager = new ObjectManager($this);
-        $this->adapter = $this->objectManager->getObject('\Magento\Framework\Image\Adapter\Gd2');
+        $this->adapter = $this->objectManager->getObject('Magento\Framework\Image\Adapter\Gd2');
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Framework/LoggerTest.php b/dev/tests/unit/testsuite/Magento/Framework/LoggerTest.php
deleted file mode 100644
index a1b3f8cdce74bd6281b15d2585c86f25cedd1aea..0000000000000000000000000000000000000000
--- a/dev/tests/unit/testsuite/Magento/Framework/LoggerTest.php
+++ /dev/null
@@ -1,211 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-namespace Magento\Framework;
-
-use Magento\Framework\App\Filesystem\DirectoryList;
-use Magento\Framework\Filesystem\Directory\Write;
-
-class LoggerTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $model = null;
-
-    /**
-     * @var \ReflectionProperty
-     */
-    protected $loggersProperty = null;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $filesystemMock;
-
-    /**
-     * @var Write | \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $directory;
-
-    /**
-     * @var string
-     */
-    private static $logDir;
-
-    public static function setUpBeforeClass()
-    {
-        self::$logDir = TESTS_TEMP_DIR . '/var/log';
-        if (!is_dir(self::$logDir)) {
-            mkdir(self::$logDir, 0777, true);
-        }
-    }
-
-    public static function tearDownAfterClass()
-    {
-        $filesystemAdapter = new \Magento\Framework\Filesystem\Driver\File();
-        $filesystemAdapter->deleteDirectory(self::$logDir);
-    }
-
-    protected function setUp()
-    {
-        $logDir = self::$logDir;
-        $this->filesystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
-        $this->directory = $this->getMock('Magento\Framework\Filesystem\Directory\Write', [], [], '', false);
-        $this->filesystemMock->expects($this->any())
-            ->method('getDirectoryWrite')
-            ->with(DirectoryList::LOG)
-            ->will($this->returnValue($this->directory));
-        $this->directory->expects($this->any())->method('create')->will($this->returnValue(true));
-        $this->directory->expects($this->any())->method('getAbsolutePath')->will(
-            $this->returnCallback(
-                function ($path) use ($logDir) {
-                    $path = ltrim($path, '\/');
-                    return $logDir . '/' . $path;
-                }
-            )
-        );
-
-        $this->model = new \Magento\Framework\Logger($this->filesystemMock);
-        $this->loggersProperty = new \ReflectionProperty($this->model, '_loggers');
-        $this->loggersProperty->setAccessible(true);
-    }
-
-    protected function tearDown()
-    {
-        $this->model = null; // will cause __descruct() in the underlying log class, which will close the open log files
-    }
-
-    /**
-     * @param string $key
-     * @param string $fileOrWrapper
-     * @dataProvider addStreamLogDataProvider
-     */
-    public function testAddStreamLog($key, $fileOrWrapper)
-    {
-        $this->assertFalse($this->model->hasLog($key));
-        $this->model->addStreamLog($key, $fileOrWrapper);
-        $this->assertTrue($this->model->hasLog($key));
-
-        $loggers = $this->loggersProperty->getValue($this->model);
-        $this->assertArrayHasKey($key, $loggers);
-        $zendLog = $loggers[$key];
-        $this->assertInstanceOf('Zend_Log', $zendLog);
-
-        $writersProperty = new \ReflectionProperty($zendLog, '_writers');
-        $writersProperty->setAccessible(true);
-        $writers = $writersProperty->getValue($zendLog);
-        $this->assertArrayHasKey(0, $writers);
-        $stream = $writers[0];
-        $this->assertInstanceOf('Zend_Log_Writer_Stream', $writers[0]);
-
-        $streamProperty = new \ReflectionProperty($stream, '_stream');
-        $streamProperty->setAccessible(true);
-        $fileOrWrapper = $streamProperty->getValue($stream);
-        $this->assertInternalType('resource', $fileOrWrapper);
-        $this->assertEquals('stream', get_resource_type($fileOrWrapper));
-    }
-
-    /**
-     * @return array
-     */
-    public function addStreamLogDataProvider()
-    {
-        return [['test', 'php://output'], ['test', 'custom_file.log'], ['test', '']];
-    }
-
-    /**
-     * @covers \Magento\Framework\Logger::hasLog
-     */
-    public function testAddLogWithSpecificKey()
-    {
-        $key = uniqid();
-        $this->model->addStreamLog($key);
-        $this->assertTrue($this->model->hasLog($key));
-    }
-
-    public function testLog()
-    {
-        $messageOne = uniqid();
-        $messageTwo = uniqid();
-        $messageThree = uniqid();
-        $this->expectOutputRegex(
-            '/' . 'DEBUG \(7\).+?' . $messageTwo . '.+?' . 'CRIT \(2\).+?' . $messageThree . '/s'
-        );
-        $this->model->addStreamLog('test', 'php://output');
-        $this->model->log($messageOne);
-        $this->model->log($messageTwo, \Zend_Log::DEBUG, 'test');
-        $this->model->log($messageThree, \Zend_Log::CRIT, 'test');
-    }
-
-    public function testLogComplex()
-    {
-        $this->expectOutputRegex('/Array\s\(\s+\[0\] => 1\s\).+stdClass Object/s');
-        $this->model->addStreamLog(\Magento\Framework\Logger::LOGGER_SYSTEM, 'php://output');
-        $this->model->log([1]);
-        $this->model->log(new \StdClass());
-        $this->model->log('key');
-    }
-
-    public function testLogNoKey()
-    {
-        $key = 'key';
-        $this->model->log($key);
-        $this->assertFalse($this->model->hasLog($key));
-    }
-
-    public function testLogDebug()
-    {
-        $message = uniqid();
-        /** @var $model \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
-        $model = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
-        $model->expects($this->at(0))
-            ->method('log')
-            ->with($message, \Zend_Log::DEBUG, \Magento\Framework\Logger::LOGGER_SYSTEM);
-        $model->expects($this->at(1))
-            ->method('log')
-            ->with(
-                $message,
-                \Zend_Log::DEBUG,
-                \Magento\Framework\Logger::LOGGER_EXCEPTION
-            );
-        $model->logDebug($message);
-        $model->logDebug($message, \Magento\Framework\Logger::LOGGER_EXCEPTION);
-    }
-
-    public function testLogException()
-    {
-        $exception = new \Exception();
-        $expected = "\n{$exception}";
-        /** @var $model \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
-        $model = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
-        $model->expects($this->at(0))
-            ->method('log')
-            ->with(
-                $expected,
-                \Zend_Log::ERR,
-                \Magento\Framework\Logger::LOGGER_EXCEPTION
-            );
-        $model->logException($exception);
-    }
-
-    public function testUnsetLoggers()
-    {
-        $key = 'test';
-        $fileOrWrapper = 'custom_file.log';
-        $this->model->addStreamLog($key, $fileOrWrapper);
-        $this->assertTrue($this->model->hasLog($key));
-        $this->model->unsetLoggers();
-        $this->assertFalse($this->model->hasLog($key));
-    }
-
-    public function testLogFile()
-    {
-        $message = ['Wrong file name', 'Avoid using special chars'];
-        $filename = 'custom_file.log';
-        $this->model->logFile($message, \Zend_Log::DEBUG);
-        $this->model->logFile($message, \Zend_Log::DEBUG, $filename);
-        $this->assertTrue($this->model->hasLog($filename));
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Message/ManagerTest.php b/dev/tests/unit/testsuite/Magento/Framework/Message/ManagerTest.php
index 96db910fd4e1c30ad0e57eb0cccf41182de4924d..32e6638df24b58263baac8e2a4d0d6bfe83e546c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Message/ManagerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Message/ManagerTest.php
@@ -29,11 +29,6 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
      */
     protected $session;
 
-    /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $logger;
-
     /**
      * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -66,11 +61,6 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
         )->disableOriginalConstructor()->setMethods(
             ['getData', 'setData']
         )->getMock();
-        $this->logger = $this->getMockBuilder(
-            'Magento\Framework\Logger'
-        )->setMethods(
-            ['logFile']
-        )->disableOriginalConstructor()->getMock();
         $this->eventManager = $this->getMockBuilder(
             'Magento\Framework\Event\Manager'
         )->setMethods(
@@ -86,7 +76,6 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
                 'messageFactory' => $this->messageFactory,
                 'session' => $this->session,
                 'eventManager' => $this->eventManager,
-                'logger' => $this->logger
             ]
         );
     }
@@ -201,16 +190,6 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
             $this->returnValue($messageError)
         );
 
-        $this->logger->expects(
-            $this->atLeastOnce()
-        )->method(
-            'logFile'
-        )->with(
-            $this->stringStartsWith($logText),
-            \Zend_Log::DEBUG,
-            \Magento\Framework\Logger::LOGGER_EXCEPTION
-        );
-
         $messageCollection = $this->getMockBuilder(
             'Magento\Framework\Message\Collection'
         )->disableOriginalConstructor()->setMethods(
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractExtensibleModelTest.php b/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractExtensibleModelTest.php
index 98eacb609f309014d80d21e645fa2c6e263a3500..26c1423a9662747db9f56968d7dd98d99b7ea159 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractExtensibleModelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractExtensibleModelTest.php
@@ -55,7 +55,7 @@ class AbstractExtensibleModelTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->contextMock = new \Magento\Framework\Model\Context(
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false),
             $this->getMock('Magento\Framework\App\CacheInterface', [], [], '', false),
             $this->getMock('Magento\Framework\App\State', [], [], '', false),
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractModelTest.php b/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractModelTest.php
index 708eeda02c8730ff19bb3aa06b8407aa8338e46e..2d2109a4b6e292e36e35fe8b40c7d78813287f68 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractModelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Model/AbstractModelTest.php
@@ -53,7 +53,7 @@ class AbstractModelTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->contextMock = new \Magento\Framework\Model\Context(
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false),
             $this->getMock('Magento\Framework\App\CacheInterface', [], [], '', false),
             $this->getMock('Magento\Framework\App\State', [], [], '', false),
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php b/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php
index 3d6b52266b576d95ef11bf390f3692b4cf87dbe6..8212036d79cc17a050c368425dbc706dbf146fb3 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php
@@ -21,7 +21,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\Data\Collection\EntityFactoryInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $entityFactoryMock;
 
-    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $loggerMock;
 
     /** @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject */
@@ -45,7 +45,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->entityFactoryMock = $this->getMock('Magento\Framework\Data\Collection\EntityFactoryInterface');
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->fetchStrategyMock = $this->getMock('Magento\Framework\Data\Collection\Db\FetchStrategyInterface');
         $this->managerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
         $this->connectionMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Setup/MigrationTest.php b/dev/tests/unit/testsuite/Magento/Framework/Module/Setup/MigrationTest.php
index 29b126f121eb4d28556e1ea2f23b7aa7e1d026ca..455753f860ecff650f25db8e20a5ecf9107a6c7c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Setup/MigrationTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Setup/MigrationTest.php
@@ -159,7 +159,7 @@ class MigrationTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($this->getMock('Magento\Framework\App\Resource', [], [], '', false)));
         $contextMock->expects($this->once())
             ->method('getLogger')
-            ->will($this->returnValue($this->getMock('Magento\Framework\Logger', [], [], '', false)));
+            ->will($this->returnValue($this->getMock('Psr\Log\LoggerInterface')));
         $contextMock->expects($this->once())
             ->method('getModulesReader')
             ->will(
@@ -216,7 +216,7 @@ class MigrationTest extends \PHPUnit_Framework_TestCase
             $this->getMock('Magento\Framework\App\Resource', [], [], '', false, false),
             $this->getMock('Magento\Framework\Filesystem', [], [], '', false),
             $this->getMock('Magento\Core\Helper\Data', [], [], '', false),
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false),
             $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'),
             $this->getMock('Magento\Framework\Module\ModuleListInterface'),
diff --git a/dev/tests/unit/testsuite/Magento/Framework/ObjectManager/ObjectManagerTest.php b/dev/tests/unit/testsuite/Magento/Framework/ObjectManager/ObjectManagerTest.php
index 9c1416a06c7aba4ffee55f9fde8e5aff9fdf4831..5a1eb47f3ecb3ee94874ae6b674feed3a979eafd 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/ObjectManager/ObjectManagerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/ObjectManager/ObjectManagerTest.php
@@ -394,6 +394,6 @@ class ObjectManagerTest extends \PHPUnit_Framework_TestCase
 
     public function testGetIgnoresFirstSlash()
     {
-        $this->assertSame($this->_object->get('Magento\Test\Di\Child'), $this->_object->get('\Magento\Test\Di\Child'));
+        $this->assertSame($this->_object->get('Magento\Test\Di\Child'), $this->_object->get('Magento\Test\Di\Child'));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
index cfd0209b33addbd652d21af589b18f25ea5bf40f..fea8b17efa8d586a54ff49febc041f1dde5cab83 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
@@ -107,7 +107,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
             ->getMockForAbstractClass();
 
         $this->adapter = $this->objectManager->getObject(
-            '\Magento\Framework\Search\Adapter\Mysql\Adapter',
+            'Magento\Framework\Search\Adapter\Mysql\Adapter',
             [
                 'mapper' => $this->mapper,
                 'responseFactory' => $this->responseFactory,
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ConditionManagerTest.php b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ConditionManagerTest.php
index 29a3e1c776025b854450c2239b95e5246e6616d4..f340d258baa76b96df82d85c1652dfe6f9186245 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ConditionManagerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ConditionManagerTest.php
@@ -57,7 +57,7 @@ class ConditionManagerTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($this->adapter));
 
         $this->conditionManager = $objectManager->getObject(
-            '\Magento\Framework\Search\Adapter\Mysql\ConditionManager',
+            'Magento\Framework\Search\Adapter\Mysql\ConditionManager',
             [
                 'resource' => $this->resource
             ]
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/DimensionsTest.php b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/DimensionsTest.php
index 729aa46274a2c22234db90f15fcb87edec714c05..72ebd5c70b190a12152a1e3539a06bb9c8d46c06 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/DimensionsTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/DimensionsTest.php
@@ -62,7 +62,7 @@ class DimensionsTest extends \PHPUnit_Framework_TestCase
             );
 
         $this->builder = $this->objectManager->getObject(
-            '\Magento\Framework\Search\Adapter\Mysql\Dimensions',
+            'Magento\Framework\Search\Adapter\Mysql\Dimensions',
             [
                 'conditionManager' => $this->conditionManager,
                 'scopeResolver' => $this->scopeResolver
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ResponseFactoryTest.php b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ResponseFactoryTest.php
index cc410bea0bf89034e21f2fbbce75c0d723edd381..fbf01248758dd9bb2db05c149eefd14dbef6f6d7 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ResponseFactoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/ResponseFactoryTest.php
@@ -72,7 +72,7 @@ class ResponseFactoryTest extends \PHPUnit_Framework_TestCase
 
         $this->objectManager->expects($this->once())->method('create')
             ->with(
-                $this->equalTo('\Magento\Framework\Search\Response\QueryResponse'),
+                $this->equalTo('Magento\Framework\Search\Response\QueryResponse'),
                 $this->equalTo(['documents' => ['document1', 'document2'], 'aggregations' => null])
             )
             ->will($this->returnValue('QueryResponseObject'));
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Validator/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/Validator/ConfigTest.php
index 3ee92e5be9001876b5c817ae81d01e5271976579..5e223a9015f4444afd2ceadfff263c3695df746a 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Validator/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Validator/ConfigTest.php
@@ -52,7 +52,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $factory = new \Magento\Framework\ObjectManager\Factory\Dynamic\Developer($config);
         $realObjectManager = new \Magento\Framework\ObjectManager\ObjectManager($factory, $config);
         $factory->setObjectManager($realObjectManager);
-        $universalFactory = $realObjectManager->get('\Magento\Framework\Validator\UniversalFactory');
+        $universalFactory = $realObjectManager->get('Magento\Framework\Validator\UniversalFactory');
         $this->_config = $this->_objectManager->getObject(
             'Magento\Framework\Validator\Config',
             ['configFiles' => $configFiles, 'builderFactory' => $universalFactory]
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MergedTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MergedTest.php
index fe0c874a755ffc31681310aafa0f35294206db4e..0075409fc18f50888ea936053eba8da3eb3e70db 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MergedTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MergedTest.php
@@ -48,7 +48,7 @@ class MergedTest extends \PHPUnit_Framework_TestCase
         $this->_assetJsTwo->expects($this->any())->method('getPath')
             ->will($this->returnValue('script_two.js'));
 
-        $this->_logger = $this->getMock('Magento\Framework\Logger', ['logException'], [], '', false);
+        $this->_logger = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->_mergeStrategy = $this->getMock('Magento\Framework\View\Asset\MergeStrategyInterface');
 
@@ -100,7 +100,7 @@ class MergedTest extends \PHPUnit_Framework_TestCase
     public function testIteratorInterfaceMerge()
     {
         $assets = [$this->_assetJsOne, $this->_assetJsTwo];
-        $this->_logger->expects($this->never())->method('logException');
+        $this->_logger->expects($this->never())->method('critical');
         $merged = new \Magento\Framework\View\Asset\Merged(
             $this->_logger,
             $this->_mergeStrategy,
@@ -135,7 +135,7 @@ class MergedTest extends \PHPUnit_Framework_TestCase
             [$this->_assetJsOne, $this->_assetJsTwo, $assetBroken]
         );
 
-        $this->_logger->expects($this->once())->method('logException')->with($this->identicalTo($mergeError));
+        $this->_logger->expects($this->once())->method('critical')->with($this->identicalTo($mergeError));
 
         $expectedResult = [$this->_assetJsOne, $this->_assetJsTwo, $assetBroken];
         $this->_assertIteratorEquals($expectedResult, $merged);
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MinifiedTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MinifiedTest.php
index 47a209618de0a357afb2886df5e3c86c59d8db25..953d28830ee18de40a5eef2d77fb15c4e3f91ed0 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MinifiedTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Asset/MinifiedTest.php
@@ -14,7 +14,7 @@ class MinifiedTest extends \PHPUnit_Framework_TestCase
     protected $_asset;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_logger;
 
@@ -51,7 +51,7 @@ class MinifiedTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->_asset = $this->getMockForAbstractClass('\Magento\Framework\View\Asset\LocalInterface');
-        $this->_logger = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $this->_logger = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $this->_baseUrl = $this->getMock('\Magento\Framework\Url', [], [], '', false);
         $this->_staticViewDir = $this->getMockForAbstractClass(
             '\Magento\Framework\Filesystem\Directory\WriteInterface'
@@ -210,7 +210,7 @@ class MinifiedTest extends \PHPUnit_Framework_TestCase
         $this->_asset->expects($this->once())->method('getContent')->will($this->returnValue('content'));
         $e = new \Exception('test');
         $this->_adapter->expects($this->once())->method('minify')->with('content')->will($this->throwException($e));
-        $this->_logger->expects($this->once())->method('logException');
+        $this->_logger->expects($this->once())->method('critical');
         $this->_staticViewDir->expects($this->never())->method('writeFile');
         $this->_asset->expects($this->once())->method('getFilePath')->will($this->returnValue('file_path'));
         $this->_asset->expects($this->once())->method('getContext')->will($this->returnValue('context'));
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php
index 79bf24db6497ec12355e34d3581a11dad2095520..a5e76e1716f578c6c93bb3f8c8f25aa54feec119 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/ContextTest.php
@@ -117,7 +117,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase
 
     public function testGetLogger()
     {
-        $this->assertInstanceOf('\Magento\Framework\Logger', $this->context->getLogger());
+        $this->assertInstanceOf('\Psr\Log\LoggerInterface', $this->context->getLogger());
     }
 
     public function testGetAppState()
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Design/Theme/ImageTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Design/Theme/ImageTest.php
index e3ab232cf713dc34e8bc27bd7f9db49188bd6573..406399dfcdadc7a2c4af07e37db9f484ea7c6efc 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/Design/Theme/ImageTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Design/Theme/ImageTest.php
@@ -86,7 +86,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase
         $this->_imageMock = $this->getMock('Magento\Framework\Image', [], [], '', false, false);
         $imageFactory->expects($this->any())->method('create')->will($this->returnValue($this->_imageMock));
 
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false, false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->_themeMock = $this->getMock('Magento\Core\Model\Theme', ['__wakeup'], [], '', false, false);
         $this->_uploaderMock = $this->getMock(
             'Magento\Framework\View\Design\Theme\Image\Uploader',
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/Link/CurrentTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/Link/CurrentTest.php
index d914dc86f1f10f93845b90697a47d65b45ac5b7e..accdfcbff9a21cf29a67d39f02e2924db34d5377 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/Link/CurrentTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Element/Html/Link/CurrentTest.php
@@ -43,7 +43,7 @@ class CurrentTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Framework\View\Element\Html\Link\Current $link */
         $link = $this->_objectManager->getObject(
-            '\Magento\Framework\View\Element\Html\Link\Current',
+            'Magento\Framework\View\Element\Html\Link\Current',
             ['urlBuilder' => $this->_urlBuilderMock]
         );
 
@@ -54,7 +54,7 @@ class CurrentTest extends \PHPUnit_Framework_TestCase
     public function testIsCurrentIfIsset()
     {
         /** @var \Magento\Framework\View\Element\Html\Link\Current $link */
-        $link = $this->_objectManager->getObject('\Magento\Framework\View\Element\Html\Link\Current');
+        $link = $this->_objectManager->getObject('Magento\Framework\View\Element\Html\Link\Current');
         $link->setCurrent(true);
         $this->assertTrue($link->IsCurrent());
     }
@@ -75,7 +75,7 @@ class CurrentTest extends \PHPUnit_Framework_TestCase
         $this->_requestMock->expects($this->once())->method('getControllerName')->will($this->returnValue('b'));
         /** @var \Magento\Framework\View\Element\Html\Link\Current $link */
         $link = $this->_objectManager->getObject(
-            '\Magento\Framework\View\Element\Html\Link\Current',
+            'Magento\Framework\View\Element\Html\Link\Current',
             [
                 'urlBuilder' => $this->_urlBuilderMock,
                 'request' => $this->_requestMock,
@@ -93,7 +93,7 @@ class CurrentTest extends \PHPUnit_Framework_TestCase
 
         /** @var \Magento\Framework\View\Element\Html\Link\Current $link */
         $link = $this->_objectManager->getObject(
-            '\Magento\Framework\View\Element\Html\Link\Current',
+            'Magento\Framework\View\Element\Html\Link\Current',
             ['urlBuilder' => $this->_urlBuilderMock, 'request' => $this->_requestMock]
         );
         $this->assertFalse($link->isCurrent());
diff --git a/dev/tests/unit/testsuite/Magento/Framework/View/Page/Config/RendererTest.php b/dev/tests/unit/testsuite/Magento/Framework/View/Page/Config/RendererTest.php
index bb04603a2056e3aaa440e0aff008cab80a59cc1c..64e3254b0bc9740a25288cb107bb59fa3b3ea020 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/View/Page/Config/RendererTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/View/Page/Config/RendererTest.php
@@ -56,7 +56,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
     protected $stringMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -106,8 +106,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->loggerMock = $this->getMockBuilder('Magento\Framework\Logger')
-            ->disableOriginalConstructor()
+        $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')
             ->getMock();
 
         $this->assetsCollection = $this->getMockBuilder('Magento\Framework\View\Asset\GroupedCollection')
@@ -316,7 +315,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
             ->willReturnArgument(0);
 
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with($exception);
 
         $this->urlBuilderMock->expects($this->once())
diff --git a/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php b/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
index e6058c1fe9e4208527f4b85c1c719e6eeab565a2..2ade264a0dcaf3fee7700e3bf6fd88dda1f9e445 100644
--- a/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
+++ b/dev/tests/unit/testsuite/Magento/GiftMessage/Helper/MessageTest.php
@@ -21,7 +21,7 @@ class MessageTest extends \PHPUnit_Framework_TestCase
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->layoutFactoryMock = $this->getMock('\Magento\Framework\View\LayoutFactory', [], [], '', false);
 
-        $this->helper = $objectManager->getObject('\Magento\GiftMessage\Helper\Message', [
+        $this->helper = $objectManager->getObject('Magento\GiftMessage\Helper\Message', [
             'layoutFactory' => $this->layoutFactoryMock,
             'skipMessageCheck' => ['onepage_checkout'],
         ]);
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAddTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAddTest.php
index ff679334640895fa66d15487ce19aa878e1a7065..f5b3c73d021e9a0f1d21856ced05ffa0b9c63f39 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAddTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/MassAddTest.php
@@ -73,10 +73,9 @@ class MassAddTest extends \PHPUnit_Framework_TestCase
         $this->flag->expects($this->once())->method('lock')
             ->will($this->throwException(new \Exception('Test exception')));
 
-        $logger = $this->getMockBuilder('Magento\Framework\Logger')->setMethods(['logException'])
-            ->disableOriginalConstructor()->getMock();
+        $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
         $this->controllerArguments['context']->getObjectManager()
-            ->expects($this->at(2))->method('get')->with('Magento\Framework\Logger')
+            ->expects($this->at(2))->method('get')->with('Psr\Log\LoggerInterface')
             ->will($this->returnValue($logger));
 
         $this->controller->execute();
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/RefreshTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/RefreshTest.php
index 78c569bed4f8133203b94d37cc7b0e2e76aa0dfb..71c385ce8f15430ae79c05110b7e9435a5a29847 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/RefreshTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Controller/Adminhtml/Googleshopping/Items/RefreshTest.php
@@ -67,10 +67,9 @@ class RefreshTest extends \PHPUnit_Framework_TestCase
         $this->flag->expects($this->once())->method('lock')
             ->will($this->throwException(new \Exception('Test exception')));
 
-        $logger = $this->getMockBuilder('Magento\Framework\Logger')->setMethods(['logException'])
-            ->disableOriginalConstructor()->getMock();
+        $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
         $this->controllerArguments['context']->getObjectManager()->expects($this->at(1))->method('get')
-            ->with('Magento\Framework\Logger')
+            ->with('Psr\Log\LoggerInterface')
             ->will($this->returnValue($logger));
 
         $this->controller->execute();
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/SalePriceEffectiveDateTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/SalePriceEffectiveDateTest.php
index d7b77c400c1db1e5c16593dab84e83ce89a0344c..bce6d2cca4a7d8e9781a341ca0e8c33a2ca4762f 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/SalePriceEffectiveDateTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/Attribute/SalePriceEffectiveDateTest.php
@@ -15,7 +15,7 @@ class SalePriceEffectiveDateTest extends \PHPUnit_Framework_TestCase
     {
         /** @var \Magento\GoogleShopping\Model\Attribute\SalePriceEffectiveDate $model */
         $model = (new \Magento\TestFramework\Helper\ObjectManager($this))
-            ->getObject('\Magento\GoogleShopping\Model\Attribute\SalePriceEffectiveDate');
+            ->getObject('Magento\GoogleShopping\Model\Attribute\SalePriceEffectiveDate');
         $product = $this->getMock('\Magento\Catalog\Model\Product', ['__wakeup'], [], '', false);
         $effectiveDateFrom = $this->getMock(
             '\Magento\GoogleShopping\Model\Attribute\DefaultAttribute',
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/MassOperationsTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/MassOperationsTest.php
index 980020bf9d4b54c6a8a4567fbabf42b4b2a692b3..72752d10b7978e22ad5ee80fe45cdbd41fbea514 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/MassOperationsTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/MassOperationsTest.php
@@ -30,7 +30,7 @@ class MassOperationsTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $storeManagerInterface;
 
-    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $logger;
 
     /** @var \Magento\GoogleShopping\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
@@ -49,7 +49,7 @@ class MassOperationsTest extends \PHPUnit_Framework_TestCase
         $this->productFactory = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $this->notificationInterface = $this->getMock('Magento\Framework\Notification\NotifierInterface');
         $this->storeManagerInterface = $this->getMock('Magento\Store\Model\StoreManagerInterface');
-        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->googleShoppingHelper = $this->getMock('Magento\GoogleShopping\Helper\Data', [], [], '', false);
         $this->googleShoppingCategoryHelper = $this->getMock('Magento\GoogleShopping\Helper\Category');
 
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ObserverTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ObserverTest.php
index 1aef8d8808af3a846411ef42018b4788e41482d0..d0bf24668cb5cee2ff4739edbbab9da960e2f873 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ObserverTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ObserverTest.php
@@ -62,7 +62,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
     {
         $this->flag->expects($this->once())->method('loadSelf')->will($this->returnSelf());
         $this->flag->expects($this->once())->method('isExpired')->will($this->returnValue(true));
-        $observer = $this->objectManagerHelper->getObject('\Magento\Framework\Event\Observer');
+        $observer = $this->objectManagerHelper->getObject('Magento\Framework\Event\Observer');
         $this->notificationInterface->expects($this->once())->method('addMajor')
             ->with(
                 'Google Shopping operation has expired.',
diff --git a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ServiceTest.php b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ServiceTest.php
index 42971cf8a13c694ee96c592189743abf5bb44bba..b4097daf20adf58e5cffca9e135222bb43937bf6 100644
--- a/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/GoogleShopping/Model/ServiceTest.php
@@ -43,7 +43,7 @@ class ServiceTest extends \PHPUnit_Framework_TestCase
         $coreRegistryMock->expects($this->any())->method('registry')->will($this->returnValue(1));
 
         $arguments = ['contentFactory' => $contentFactoryMock, 'coreRegistry' => $coreRegistryMock];
-        $this->_model = $this->_helper->getObject('\Magento\GoogleShopping\Model\Service', $arguments);
+        $this->_model = $this->_helper->getObject('Magento\GoogleShopping\Model\Service', $arguments);
     }
 
     public function testGetService()
diff --git a/dev/tests/unit/testsuite/Magento/GroupedProduct/Controller/Adminhtml/Edit/PopupTest.php b/dev/tests/unit/testsuite/Magento/GroupedProduct/Controller/Adminhtml/Edit/PopupTest.php
index 9473104ee5d03d322fe2008aaf709cdbbf5b8fd2..cc11f721b5dffaff38f21456f12997f4dc7660b7 100644
--- a/dev/tests/unit/testsuite/Magento/GroupedProduct/Controller/Adminhtml/Edit/PopupTest.php
+++ b/dev/tests/unit/testsuite/Magento/GroupedProduct/Controller/Adminhtml/Edit/PopupTest.php
@@ -45,7 +45,7 @@ class PopupTest extends \PHPUnit_Framework_TestCase
 
         $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->action = $this->objectManager->getObject(
-            '\Magento\GroupedProduct\Controller\Adminhtml\Edit\Popup',
+            'Magento\GroupedProduct\Controller\Adminhtml\Edit\Popup',
             [
                 'request' => $this->request,
                 'factory' => $this->factory,
diff --git a/dev/tests/unit/testsuite/Magento/GroupedProduct/Model/Product/Type/GroupedTest.php b/dev/tests/unit/testsuite/Magento/GroupedProduct/Model/Product/Type/GroupedTest.php
index ad9392e906ed301fdbefc334be9d9e526d1018d4..cd98cd9ee707d8cf2783d51313915d73dcfc2c11 100644
--- a/dev/tests/unit/testsuite/Magento/GroupedProduct/Model/Product/Type/GroupedTest.php
+++ b/dev/tests/unit/testsuite/Magento/GroupedProduct/Model/Product/Type/GroupedTest.php
@@ -40,7 +40,7 @@ class GroupedTest extends \PHPUnit_Framework_TestCase
         $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
         $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
         $this->product = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $productFactoryMock = $this->getMock('Magento\Catalog\Model\ProductFactory', [], [], '', false);
         $this->catalogProductLink = $this->getMock(
             '\Magento\GroupedProduct\Model\Resource\Product\Link',
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/ExportTest.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/ExportTest.php
index 582bfb7111443e14369e1d2edb1af906de5c8e95..ce1d09e5366bbaa936b735b099c8a11f94c9ff3d 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/ExportTest.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/ExportTest.php
@@ -57,9 +57,8 @@ class ExportTest extends \PHPUnit_Framework_TestCase
             $this->returnValue($this->_exportFileExtension)
         );
 
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
-        $adapterFactory = $this->getMock('Magento\Framework\Logger\AdapterFactory', [], [], '', false);
         $entityFactory = $this->getMock(
             'Magento\ImportExport\Model\Export\Entity\Factory',
             [],
@@ -78,7 +77,7 @@ class ExportTest extends \PHPUnit_Framework_TestCase
         $mockModelExport = $this->getMock(
             'Magento\ImportExport\Model\Export',
             ['getEntityAdapter', '_getEntityAdapter', '_getWriter'],
-            [$logger, $filesystem, $adapterFactory, $this->_exportConfigMock, $entityFactory, $exportAdapterFac]
+            [$logger, $filesystem, $this->_exportConfigMock, $entityFactory, $exportAdapterFac]
         );
         $mockModelExport->expects(
             $this->any()
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Resource/CollectionByPagesIteratorTest.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Resource/CollectionByPagesIteratorTest.php
index 15b1b6c5660d3606025433e67b5c11a087398d1a..4b3e456e4675fc079ac2257fd2bc64eee28952f1 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Resource/CollectionByPagesIteratorTest.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Resource/CollectionByPagesIteratorTest.php
@@ -41,7 +41,7 @@ class CollectionByPagesIteratorTest extends \PHPUnit_Framework_TestCase
         $select = $this->getMock('Zend_Db_Select', [], [], '', false);
 
         $entityFactory = $this->getMock('Magento\Core\Model\EntityFactory', [], [], '', false);
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
 
         /** @var $collectionMock \Magento\Framework\Data\Collection\Db|PHPUnit_Framework_MockObject_MockObject */
         $collectionMock = $this->getMock(
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php b/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php
index 4332d4ce46af64febc4a5e37dd49ab14b155b7ed..4e27d2ab84a864e0b107037a32f007dc690a2314 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php
@@ -24,7 +24,7 @@ abstract class IntegrationTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $_objectManagerMock;
 
-    /** @var \Magento\Backend\Model\Layout\Filter\Acl|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Backend\Model\View\Layout\Filter\Acl|\PHPUnit_Framework_MockObject_MockObject */
     protected $_layoutFilterMock;
 
     /** @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */
@@ -190,10 +190,10 @@ abstract class IntegrationTest extends \PHPUnit_Framework_TestCase
         $menuMock = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
-        $loggerMock = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
-        $loggerMock->expects($this->any())->method('logException')->will($this->returnSelf());
+        $loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+        $loggerMock->expects($this->any())->method('critical')->will($this->returnSelf());
         $menuMock->expects($this->any())->method('getParentItems')->will($this->returnValue([]));
         $blockMock->expects($this->any())->method('getMenuModel')->will($this->returnValue($menuMock));
         $this->_layoutMock->expects($this->any())->method('getMessagesBlock')->will($this->returnValue($blockMock));
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php b/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php
index d2d4d092c67d3934adbd71d08fc4a6a150ad5796..570c7c0db3259713599bd8a7a9b9a858216ad8e4 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php
@@ -18,7 +18,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\HTTP\ZendClient */
     protected $_httpClientMock;
 
-    /** @var \Magento\Integration\Model\Oauth\Token\Factory */
+    /** @var \Magento\Integration\Model\Oauth\TokenFactory */
     protected $_tokenFactory;
 
     /** @var \Magento\Integration\Model\Oauth\Token */
@@ -33,7 +33,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Integration\Service\V1\OauthInterface */
     protected $_oauthService;
 
-    /** @var \Magento\Framework\Logger */
+    /** @var \Psr\Log\LoggerInterface */
     protected $_loggerMock;
 
     protected function setUp()
@@ -53,8 +53,8 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_tokenFactory = $this->getMockBuilder(
-            'Magento\Integration\Model\Oauth\Token\Factory'
-        )->disableOriginalConstructor()->getMock();
+            'Magento\Integration\Model\Oauth\TokenFactory'
+        )->disableOriginalConstructor()->setMethods(['create'])->getMock();
         $this->_tokenMock = $this->getMockBuilder(
             'Magento\Integration\Model\Oauth\Token'
         )->disableOriginalConstructor()->getMock();
@@ -90,9 +90,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
             'Magento\Framework\HTTP\ZendClient'
         )->disableOriginalConstructor()->getMock();
         $this->_loggerMock = $this->getMockBuilder(
-            'Magento\Framework\Logger'
-        )->disableOriginalConstructor()->setMethods(
-            ['logException']
+            'Psr\Log\LoggerInterface'
         )->getMock();
 
         $this->_oauthService = new \Magento\Integration\Service\V1\Oauth(
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php b/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
index b510a867cd1dfb7ec41d877260bce2ed1d9e16c5..9daf41a124f02c23b61eec6aba6d88e9aebd4590 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
@@ -15,7 +15,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Integration\Model\Oauth\Nonce\Factory */
     private $_nonceFactory;
 
-    /** @var \Magento\Integration\Model\Oauth\Token\Factory */
+    /** @var \Magento\Integration\Model\Oauth\TokenFactory */
     private $_tokenFactory;
 
     /** @var \Magento\Integration\Model\Oauth\Consumer */
@@ -76,8 +76,8 @@ class OauthTest extends \PHPUnit_Framework_TestCase
             'Magento\Integration\Model\Oauth\Nonce\Factory'
         )->disableOriginalConstructor()->getMock();
         $this->_tokenFactory = $this->getMockBuilder(
-            'Magento\Integration\Model\Oauth\Token\Factory'
-        )->disableOriginalConstructor()->getMock();
+            'Magento\Integration\Model\Oauth\TokenFactory'
+        )->disableOriginalConstructor()->setMethods(['create'])->getMock();
         $this->_tokenMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token')
             ->disableOriginalConstructor()
             ->setMethods(
@@ -122,8 +122,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
             $this->_consumerFactory,
             $this->_tokenFactory,
             $this->_dataHelperMock,
-            $this->_dateMock,
-            $this->_tokenMock
+            $this->_dateMock
         );
         $this->_oauth = new \Magento\Framework\Oauth\Oauth(
             $this->_oauthHelperMock,
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php
index fd528c328f05bb91b9d299cfb4da014274d45d94..e69c373d7913aef09ca38f785ea8c3ceebd03df1 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AdminTokenServiceTest.php
@@ -15,8 +15,8 @@ class AdminTokenServiceTest extends \PHPUnit_Framework_TestCase
     /** \Magento\Integration\Service\V1\AdminTokenService */
     protected $_tokenService;
 
-    /** \Magento\Integration\Model\Oauth\Token\Factory|\PHPUnit_Framework_MockObject_MockObject */
-    protected $_tokenModelFactoryMock;
+    /** \Magento\Integration\Model\Oauth\TokenFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $_tokenFactoryMock;
 
     /** \Magento\User\Model\User|\PHPUnit_Framework_MockObject_MockObject */
     protected $_userModelMock;
@@ -35,10 +35,11 @@ class AdminTokenServiceTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->_tokenModelFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token\Factory')
+        $this->_tokenFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\TokenFactory')
             ->setMethods(['create'])
             ->disableOriginalConstructor()
             ->getMock();
+        $this->_tokenFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_tokenMock));
 
         $this->_userModelMock = $this->getMockBuilder('Magento\User\Model\User')
             ->disableOriginalConstructor()
@@ -67,7 +68,7 @@ class AdminTokenServiceTest extends \PHPUnit_Framework_TestCase
         )->disableOriginalConstructor()->getMock();
 
         $this->_tokenService = new \Magento\Integration\Service\V1\AdminTokenService(
-            $this->_tokenModelFactoryMock,
+            $this->_tokenFactoryMock,
             $this->_userModelMock,
             $this->_tokenModelCollectionFactoryMock,
             $this->validatorHelperMock
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
index 73aeef14728a5bbc836f3e0df71d8b9b62c7f58c..b0a84bce0c52246e13f25a5bb3371d3e1b52c18d 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/AuthorizationServiceTest.php
@@ -43,7 +43,7 @@ class AuthorizationServiceTest extends \PHPUnit_Framework_TestCase
             $this->getMock('Magento\Authorization\Model\Resource\Role\CollectionFactory', [], [], '', false),
             $this->getMock('Magento\Authorization\Model\RulesFactory', [], [], '', false),
             $this->getMock('Magento\Authorization\Model\Resource\Rules\CollectionFactory', [], [], '', false),
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMock('Magento\Framework\Acl\RootResource', [], [], '', false)
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php
index 5e4581da4527a52cdd266ea432cbdc0be2ce75b3..43704ebb9e04e4930c41fffffe0e5014df174079 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/CustomerTokenServiceTest.php
@@ -15,8 +15,8 @@ class CustomerTokenServiceTest extends \PHPUnit_Framework_TestCase
     /** \Magento\Integration\Service\V1\CustomerTokenService */
     protected $_tokenService;
 
-    /** \Magento\Integration\Model\Oauth\Token\Factory|\PHPUnit_Framework_MockObject_MockObject */
-    protected $_tokenModelFactoryMock;
+    /** \Magento\Integration\Model\Oauth\TokenFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $_tokenFactoryMock;
 
     /** \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $_accountManagementMock;
@@ -35,10 +35,11 @@ class CustomerTokenServiceTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $this->_tokenModelFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token\Factory')
+        $this->_tokenFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\TokenFactory')
             ->setMethods(['create'])
             ->disableOriginalConstructor()
             ->getMock();
+        $this->_tokenFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_tokenMock));
 
         $this->_accountManagementMock = $this
             ->getMockBuilder('Magento\Customer\Api\AccountManagementInterface')
@@ -68,7 +69,7 @@ class CustomerTokenServiceTest extends \PHPUnit_Framework_TestCase
         )->disableOriginalConstructor()->getMock();
 
         $this->_tokenService = new \Magento\Integration\Service\V1\CustomerTokenService(
-            $this->_tokenModelFactoryMock,
+            $this->_tokenFactoryMock,
             $this->_accountManagementMock,
             $this->_tokenModelCollectionFactoryMock,
             $this->validatorHelperMock
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
index eaeb90e7e172c99da148ac64a01e3231bc2b78e8..ed6d24237386dc6c76a007e874f4b5555074f3b0 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
@@ -41,7 +41,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     private $_consumerData;
 
     /**
-     * @var \Magento\Integration\Model\Oauth\Token\Factory|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Integration\Model\Oauth\TokenFactory|\PHPUnit_Framework_MockObject_MockObject
      */
     private $_tokenFactoryMock;
 
@@ -60,12 +60,13 @@ class OauthTest extends \PHPUnit_Framework_TestCase
         )->getMock();
 
         $this->_tokenFactoryMock = $this->getMock(
-            'Magento\Integration\Model\Oauth\Token\Factory',
-            [],
+            'Magento\Integration\Model\Oauth\TokenFactory',
+            ['create'],
             [],
             '',
             false
         );
+        $this->_tokenFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_tokenMock));
         $this->_consumerMock = $this->getMockBuilder(
             'Magento\Integration\Model\Oauth\Consumer'
         )->disableOriginalConstructor()->setMethods(
@@ -94,7 +95,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
             $this->_tokenFactoryMock,
             $this->getMock('Magento\Integration\Helper\Oauth\Data', [], [], '', false),
             $this->getMock('Magento\Framework\HTTP\ZendClient', [], [], '', false),
-            $this->getMock('Magento\Framework\Logger', [], [], '', false),
+            $this->getMock('Psr\Log\LoggerInterface'),
             $this->getMock('Magento\Framework\Oauth\Helper\Oauth', [], [], '', false),
             $this->_tokenProviderMock
         );
diff --git a/dev/tests/unit/testsuite/Magento/LayeredNavigation/Block/NavigationTest.php b/dev/tests/unit/testsuite/Magento/LayeredNavigation/Block/NavigationTest.php
index 20cc60ccd344ad5a59a086ec3e5f9e824b2e7075..4acd06a43f9266237f14c87e04008fc2d2cddc22 100644
--- a/dev/tests/unit/testsuite/Magento/LayeredNavigation/Block/NavigationTest.php
+++ b/dev/tests/unit/testsuite/Magento/LayeredNavigation/Block/NavigationTest.php
@@ -55,7 +55,7 @@ class NavigationTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->model = $objectManager->getObject(
-            '\Magento\LayeredNavigation\Block\Navigation',
+            'Magento\LayeredNavigation\Block\Navigation',
             [
                 'layerResolver' => $layerResolver,
                 'filterList' => $this->filterListMock,
diff --git a/dev/tests/unit/testsuite/Magento/Multishipping/Controller/Checkout/Address/EditAddressTest.php b/dev/tests/unit/testsuite/Magento/Multishipping/Controller/Checkout/Address/EditAddressTest.php
index a16266fae67fb4504886cbe2019dd8f1cb28f505..458b6a186d1a22d73ae01e58835fa48d2371c328 100644
--- a/dev/tests/unit/testsuite/Magento/Multishipping/Controller/Checkout/Address/EditAddressTest.php
+++ b/dev/tests/unit/testsuite/Magento/Multishipping/Controller/Checkout/Address/EditAddressTest.php
@@ -88,7 +88,7 @@ class EditAddressTest extends \PHPUnit_Framework_TestCase
         $this->pageMock->expects($this->any())->method('getConfig')->willReturn($this->configMock);
         $this->configMock->expects($this->any())->method('getTitle')->willReturn($this->titleMock);
         $this->viewMock->expects($this->any())->method('getPage')->willReturn($this->pageMock);
-        $this->controller = $objectManager->getObject('\Magento\Multishipping\Controller\Checkout\Address\EditAddress',
+        $this->controller = $objectManager->getObject('Magento\Multishipping\Controller\Checkout\Address\EditAddress',
             ['context' => $contextMock]);
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/BanktransferTest.php b/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/BanktransferTest.php
index 6c96fbfa42616add8f2f756e44fde042ec89f0a8..03f21339f631bda635b1cd238f60c3443e498519 100644
--- a/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/BanktransferTest.php
+++ b/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/BanktransferTest.php
@@ -17,20 +17,12 @@ class BanktransferTest extends \PHPUnit_Framework_TestCase
         $eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $paymentDataMock = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
         $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
-        $adapterFactoryMock = $this->getMock(
-            'Magento\Framework\Logger\AdapterFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
         $this->_object = $objectManagerHelper->getObject(
             'Magento\OfflinePayments\Model\Banktransfer',
             [
                 'eventManager' => $eventManager,
                 'paymentData' => $paymentDataMock,
                 'scopeConfig' => $scopeConfig,
-                'logAdapterFactory' => $adapterFactoryMock
             ]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/CashondeliveryTest.php b/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/CashondeliveryTest.php
index 651183471b28a3df7cb4c9f2d9ff487b65707c6d..2f3cb65cfc398b73c8f49322d261b8a1bf18b654 100644
--- a/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/CashondeliveryTest.php
+++ b/dev/tests/unit/testsuite/Magento/OfflinePayments/Model/CashondeliveryTest.php
@@ -17,13 +17,6 @@ class CashondeliveryTest extends \PHPUnit_Framework_TestCase
 
         $eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $paymentDataMock = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
-        $adapterFactoryMock = $this->getMock(
-            'Magento\Framework\Logger\AdapterFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
 
         $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
         $this->_object = $helper->getObject(
@@ -32,7 +25,6 @@ class CashondeliveryTest extends \PHPUnit_Framework_TestCase
                 'eventManager' => $eventManager,
                 'paymentData' => $paymentDataMock,
                 'scopeConfig' => $scopeConfig,
-                'logAdapterFactory' => $adapterFactoryMock
             ]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Payment/Block/Info/ContainerAbstractTest.php b/dev/tests/unit/testsuite/Magento/Payment/Block/Info/ContainerAbstractTest.php
index 0891b30fc9359eb3fd1629ede98535c4ac71448f..a2974944cb1df368dfffc49ce18a68bbd2e127fd 100644
--- a/dev/tests/unit/testsuite/Magento/Payment/Block/Info/ContainerAbstractTest.php
+++ b/dev/tests/unit/testsuite/Magento/Payment/Block/Info/ContainerAbstractTest.php
@@ -21,17 +21,7 @@ class ContainerAbstractTest extends \PHPUnit_Framework_TestCase
         );
         $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
         $paymentInfo = $objectManagerHelper->getObject('Magento\Payment\Model\Info');
-        $adapterFactoryMock = $this->getMock(
-            'Magento\Framework\Logger\AdapterFactory',
-            ['create'],
-            [],
-            '',
-            false
-        );
-        $methodInstance = $objectManagerHelper->getObject(
-            'Magento\OfflinePayments\Model\Checkmo',
-            ['logAdapterFactory' => $adapterFactoryMock]
-        );
+        $methodInstance = $objectManagerHelper->getObject('Magento\OfflinePayments\Model\Checkmo');
         $paymentInfo->setMethodInstance($methodInstance);
         $block->expects($this->atLeastOnce())->method('getPaymentInfo')->will($this->returnValue($paymentInfo));
 
diff --git a/dev/tests/unit/testsuite/Magento/Payment/Model/Method/FreeTest.php b/dev/tests/unit/testsuite/Magento/Payment/Model/Method/FreeTest.php
index e927fe780dac5e5af893b50cf29ff229555f4253..11571cbb2f964f64bfeec9f8bd26f89e1584ad24 100644
--- a/dev/tests/unit/testsuite/Magento/Payment/Model/Method/FreeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Payment/Model/Method/FreeTest.php
@@ -20,14 +20,14 @@ class FreeTest extends \PHPUnit_Framework_TestCase
         $eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $paymentData  = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
         $this->scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
-        $logAdapterFactory = $this->getMock('Magento\Framework\Logger\AdapterFactory', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->currencyPrice = $this->getMockBuilder('Magento\Framework\Pricing\PriceCurrencyInterface')->getMock();
 
         $this->methodFree = new \Magento\Payment\Model\Method\Free(
             $eventManager,
             $paymentData,
             $this->scopeConfig,
-            $logAdapterFactory,
+            $logger,
             $this->currencyPrice
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Payment/Model/MethodListTest.php b/dev/tests/unit/testsuite/Magento/Payment/Model/MethodListTest.php
index a6f181262c94c335a14e867e13a624b9efeaafaa..c4dc8081188e5f089f6605145935bfd99bce0600 100644
--- a/dev/tests/unit/testsuite/Magento/Payment/Model/MethodListTest.php
+++ b/dev/tests/unit/testsuite/Magento/Payment/Model/MethodListTest.php
@@ -35,7 +35,7 @@ class MethodListTest extends \PHPUnit_Framework_TestCase
             '\Magento\Payment\Model\Checks\SpecificationFactory', [], [], '', false
         );
         $this->methodList = $this->objectManager->getObject(
-            '\Magento\Payment\Model\MethodList',
+            'Magento\Payment\Model\MethodList',
             [
                 'paymentHelper' => $this->paymentHelperMock,
                 'specificationFactory' => $this->specificationFactoryMock
diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9237b9f7ff895f02c4394d41bbc7d0e0803b0d9d
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php
@@ -0,0 +1,356 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Persistent\Block\Header;
+
+/**
+ * Class AdditionalTest
+ */
+class AdditionalTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Customer\Helper\View|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerViewHelperMock;
+
+    /**
+     * @var \Magento\Persistent\Helper\Session|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $persistentSessionHelperMock;
+
+    /**
+     * Customer repository
+     *
+     * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerRepositoryMock;
+
+    /**
+     * @var \Magento\Framework\View\Element\Template\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManagerMock;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $scopeConfigMock;
+
+    /**
+     * @var \Magento\Framework\App\Cache\StateInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $cacheStateMock;
+
+    /**
+     * @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $cacheMock;
+
+    /**
+     * @var \Magento\Framework\Session\SidResolverInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $sidResolverMock;
+
+    /**
+     * @var \Magento\Framework\Session\SessionManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $sessionMock;
+
+    /**
+     * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $escaperMock;
+
+    /**
+     * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $urlBuilderMock;
+
+    /**
+     * @var \Magento\Persistent\Block\Header\Additional
+     */
+    protected $additional;
+
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->contextMock = $this->getMock(
+            'Magento\Framework\View\Element\Template\Context',
+            [
+                'getEventManager',
+                'getScopeConfig',
+                'getCacheState',
+                'getCache',
+                'getInlineTranslation',
+                'getSidResolver',
+                'getSession',
+                'getEscaper',
+                'getUrlBuilder'
+            ],
+            [],
+            '',
+            false
+        );
+        $this->customerViewHelperMock = $this->getMock(
+            'Magento\Customer\Helper\View',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->persistentSessionHelperMock = $this->getMock(
+            'Magento\Persistent\Helper\Session',
+            ['getSession'],
+            [],
+            '',
+            false
+        );
+        $this->customerRepositoryMock = $this->getMockForAbstractClass(
+            'Magento\Customer\Api\CustomerRepositoryInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getById']
+        );
+
+        $this->eventManagerMock = $this->getMockForAbstractClass(
+            'Magento\Framework\Event\ManagerInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['dispatch']
+        );
+        $this->scopeConfigMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\Config\ScopeConfigInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getValue']
+        );
+        $this->cacheStateMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\Cache\StateInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['isEnabled']
+        );
+        $this->cacheMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\CacheInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['load']
+        );
+        $this->sidResolverMock = $this->getMockForAbstractClass(
+            'Magento\Framework\Session\SidResolverInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getSessionIdQueryParam']
+        );
+        $this->sessionMock = $this->getMockForAbstractClass(
+            'Magento\Framework\Session\SessionManagerInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getSessionId']
+        );
+        $this->escaperMock = $this->getMockForAbstractClass(
+            'Magento\Framework\Escaper',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['escapeHtml']
+        );
+        $this->urlBuilderMock = $this->getMockForAbstractClass(
+            'Magento\Framework\UrlInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getUrl']
+        );
+
+        $this->contextMock->expects($this->once())
+            ->method('getEventManager')
+            ->willReturn($this->eventManagerMock);
+        $this->contextMock->expects($this->once())
+            ->method('getScopeConfig')
+            ->willReturn($this->scopeConfigMock);
+        $this->contextMock->expects($this->once())
+            ->method('getCacheState')
+            ->willReturn($this->cacheStateMock);
+        $this->contextMock->expects($this->once())
+            ->method('getCache')
+            ->willReturn($this->cacheMock);
+        $this->contextMock->expects($this->once())
+            ->method('getSidResolver')
+            ->willReturn($this->sidResolverMock);
+        $this->contextMock->expects($this->once())
+            ->method('getSession')
+            ->willReturn($this->sessionMock);
+        $this->contextMock->expects($this->once())
+            ->method('getEscaper')
+            ->willReturn($this->escaperMock);
+        $this->contextMock->expects($this->once())
+            ->method('getUrlBuilder')
+            ->willReturn($this->urlBuilderMock);
+
+        $this->additional = $this->objectManager->getObject(
+            'Magento\Persistent\Block\Header\Additional',
+            [
+                'context' => $this->contextMock,
+                'customerViewHelper' => $this->customerViewHelperMock,
+                'persistentSessionHelper' => $this->persistentSessionHelperMock,
+                'customerRepository' => $this->customerRepositoryMock,
+                'data' => []
+            ]
+        );
+    }
+
+    /**
+     * Run test toHtml method
+     *
+     * @param bool $customerId
+     * @return void
+     *
+     * @dataProvider dataProviderToHtml
+     */
+    public function testToHtml($customerId)
+    {
+        $cacheData = false;
+        $idQueryParam = 'id-query-param';
+        $sessionId = 'session-id';
+        $customerName = 'customer-name';
+
+        $this->additional->setData('cache_lifetime', 789);
+        $this->additional->setData('cache_key', 'cache-key');
+
+        $this->eventManagerMock->expects($this->once())
+            ->method('dispatch')
+            ->with('view_block_abstract_to_html_before', ['block' => $this->additional]);
+        $this->scopeConfigMock->expects($this->once())
+            ->method('getValue')
+            ->with(
+                'advanced/modules_disable_output/Magento_Persistent',
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            )->willReturn(false);
+
+        // get cache
+        $this->cacheStateMock->expects($this->at(0))
+            ->method('isEnabled')
+            ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP)
+            ->willReturn(true);
+        // save cache
+        $this->cacheStateMock->expects($this->at(1))
+            ->method('isEnabled')
+            ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP)
+            ->willReturn(false);
+
+        $this->cacheMock->expects($this->once())
+            ->method('load')
+            ->willReturn($cacheData);
+        $this->sidResolverMock->expects($this->never())
+            ->method('getSessionIdQueryParam')
+            ->with($this->sessionMock)
+            ->willReturn($idQueryParam);
+        $this->sessionMock->expects($this->never())
+            ->method('getSessionId')
+            ->willReturn($sessionId);
+
+        // call protected _toHtml method
+        $sessionMock = $this->getMock(
+            'Magento\Persistent\Model\Session',
+            ['getCustomerId'],
+            [],
+            '',
+            false
+        );
+
+        $this->persistentSessionHelperMock->expects($this->atLeastOnce())
+            ->method('getSession')
+            ->willReturn($sessionMock);
+
+        $sessionMock->expects($this->atLeastOnce())
+            ->method('getCustomerId')
+            ->willReturn($customerId);
+
+        if ($customerId) {
+
+            $customerMock = $this->getMockForAbstractClass(
+                'Magento\Customer\Api\Data\CustomerInterface',
+                [],
+                '',
+                false,
+                true,
+                true,
+                []
+            );
+
+            $this->customerRepositoryMock->expects($this->once())
+                ->method('getById')
+                ->with($customerId)
+                ->willReturn($customerMock);
+
+            $this->customerViewHelperMock->expects($this->once())
+                ->method('getCustomerName')
+                ->with($customerMock)
+                ->willReturn($customerName);
+
+            $this->escaperMock->expects($this->at(0))
+                ->method('escapeHtml')
+                ->with($customerName)
+                ->willReturn($customerName);
+
+            $this->assertEquals('<span><a  >(Not customer-name?)</a></span>', $this->additional->toHtml());
+        } else {
+            $this->assertEquals('', $this->additional->toHtml());
+        }
+    }
+
+    /**
+     * Data provider for dataProviderToHtml method
+     *
+     * @return array
+     */
+    public function dataProviderToHtml()
+    {
+        return [
+            ['customerId' => 2],
+            ['customerId' => null],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Helper/DataTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Helper/DataTest.php
index 0dee70ce932df811c867b2ebae3126eaec78b1e3..313b4830bb091e73b6118ac1fd874965ec79d02b 100644
--- a/dev/tests/unit/testsuite/Magento/Persistent/Helper/DataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Persistent/Helper/DataTest.php
@@ -21,7 +21,7 @@ class DataTest extends \PHPUnit_Framework_TestCase
         $this->_modulesReader = $this->getMock('\Magento\Framework\Module\Dir\Reader', [], [], '', false);
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->_helper = $objectManager->getObject(
-            '\Magento\Persistent\Helper\Data',
+            'Magento\Persistent\Helper\Data',
             ['modulesReader' => $this->_modulesReader]
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e92b86b297d766ee1e177c0d5679bdc65cb4faf
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Persistent\Model\Layout;
+
+/**
+ * Class DepersonalizePluginTest
+ */
+class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Persistent\Model\Session|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $persistentSessionMock;
+
+    /**
+     * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $moduleManagerMock;
+
+    /**
+     * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $cacheConfigMock;
+
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Persistent\Model\Layout\DepersonalizePlugin
+     */
+    protected $plugin;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->persistentSessionMock = $this->getMock(
+            'Magento\Persistent\Model\Session',
+            ['setCustomerId'],
+            [],
+            '',
+            false
+        );
+
+        $this->requestMock = $this->getMockForAbstractClass(
+            'Magento\Framework\App\RequestInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['isAjax']
+        );
+        $this->moduleManagerMock = $this->getMock(
+            'Magento\Framework\Module\Manager',
+            ['isEnabled'],
+            [],
+            '',
+            false
+        );
+        $this->cacheConfigMock = $this->getMock(
+            'Magento\PageCache\Model\Config',
+            ['isEnabled'],
+            [],
+            '',
+            false
+        );
+
+        $this->plugin = $this->objectManager->getObject(
+            'Magento\Persistent\Model\Layout\DepersonalizePlugin',
+            [
+                'persistentSession' => $this->persistentSessionMock,
+                'request' => $this->requestMock,
+                'moduleManager' => $this->moduleManagerMock,
+                'cacheConfig' => $this->cacheConfigMock
+            ]
+        );
+    }
+
+    /**
+     * Run test afterGenerateXml method
+     *
+     * @param bool $result
+     *
+     * @dataProvider dataProviderAfterGenerateXml
+     */
+    public function testAfterGenerateXml($result)
+    {
+        /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $subjectMock */
+        $subjectMock = $this->getMockForAbstractClass(
+            'Magento\Framework\View\LayoutInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['isCacheable']
+        );
+        /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $resultMock */
+        $resultMock = $this->getMockForAbstractClass(
+            'Magento\Framework\View\LayoutInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            []
+        );
+
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn($result);
+        $this->cacheConfigMock->expects($this->any())
+            ->method('isEnabled')
+            ->willReturn($result);
+        $this->requestMock->expects($this->any())
+            ->method('isAjax')
+            ->willReturn(!$result);
+        $subjectMock->expects($this->any())
+            ->method('isCacheable')
+            ->willReturn($result);
+
+        if ($result) {
+            $this->persistentSessionMock->expects($this->once())
+                ->method('setCustomerId')
+                ->with(null);
+        } else {
+            $this->persistentSessionMock->expects($this->never())
+                ->method('setCustomerId')
+                ->with(null);
+        }
+
+        $this->assertEquals($resultMock, $this->plugin->afterGenerateXml($subjectMock, $resultMock));
+    }
+
+    /**
+     * Data provider for testAfterGenerateXml
+     *
+     * @return array
+     */
+    public function dataProviderAfterGenerateXml()
+    {
+        return [
+            ['result' => true],
+            ['result' => false]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Reports/Model/Resource/Report/Collection/AbstractCollectionTest.php b/dev/tests/unit/testsuite/Magento/Reports/Model/Resource/Report/Collection/AbstractCollectionTest.php
index f8bfd4a06e5a67430e78ad550659d972f2bb850c..69d555efe558d71bd3027b9208f0c7ed3ff3ed43 100644
--- a/dev/tests/unit/testsuite/Magento/Reports/Model/Resource/Report/Collection/AbstractCollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Reports/Model/Resource/Report/Collection/AbstractCollectionTest.php
@@ -14,7 +14,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $entityFactory = $this->getMock('\Magento\Core\Model\EntityFactory', [], [], '', false);
-        $logger = $this->getMock('\Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('\Psr\Log\LoggerInterface', [], [], '', false);
         $fetchStrategy = $this->getMock('\Magento\Framework\Data\Collection\Db\FetchStrategy\Query', [], [], '', false);
         $eventManager = $this->getMock('\Magento\Framework\Event\Manager', [], [], '', false);
         $connection = $this->getMock('\Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false);
diff --git a/dev/tests/unit/testsuite/Magento/Review/Model/Resource/Review/Summary/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Review/Model/Resource/Review/Summary/CollectionTest.php
index 57e071b3ce9539eb0e4928cf393c727e5880c939..2fc0f29b85572786adbc98bd1af47f07dc5196b9 100644
--- a/dev/tests/unit/testsuite/Magento/Review/Model/Resource/Review/Summary/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Review/Model/Resource/Review/Summary/CollectionTest.php
@@ -23,7 +23,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
     protected $entityFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $loggerMock;
 
@@ -58,7 +58,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock('Magento\Framework\Logger', ['log'], [], '', false);
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->resourceMock = $this->getMock(
             'Magento\Framework\App\Resource',
             [],
diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php
index ba41ccae4d43eb879a598c7b938a958421f704ea..9d1f9f3ac6f0af6db46d7c80c0e1cdff08bc0231 100644
--- a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php
@@ -106,6 +106,48 @@ class AbstractConditionTest extends \PHPUnit_Framework_TestCase
         );
     }
 
+    /**
+     * @param $existingValue
+     * @param $operator
+     * @param $valueForValidate
+     * @param $expectedResult
+     *
+     * @dataProvider validateAttributeDataProvider
+     */
+    public function testValidate($existingValue, $operator, $valueForValidate, $expectedResult)
+    {
+        $objectMock = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ['hasData', 'load', 'getId', 'getData'],
+            [],
+            '',
+            false
+        );
+        $objectMock->expects($this->once())
+            ->method('hasData')
+            ->willReturn(false);
+        $objectMock->expects($this->once())
+            ->method('getId')
+            ->willReturn(7);
+        $objectMock->expects($this->once())
+            ->method('load')
+            ->with(7);
+        $objectMock->expects($this->once())
+            ->method('getData')
+            ->willReturn($valueForValidate);
+
+        $this->_condition->setOperator($operator);
+        $this->_condition->setData('value_parsed', $existingValue);
+        $this->assertEquals(
+            $expectedResult,
+            $this->_condition->validate($objectMock),
+            "Failed asserting that "
+            . var_export($existingValue, true)
+            . $operator
+            . var_export($valueForValidate, true)
+        );
+    }
+
     public function validateAttributeArrayInputTypeDataProvider()
     {
         return [
diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/CombineTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/CombineTest.php
index f33ecb18752f46595fc1bf504a89568e921826d5..109f79c4b2298c07194f2012d9f0e86bfe6b506c 100644
--- a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/CombineTest.php
+++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/CombineTest.php
@@ -20,7 +20,7 @@ class CombineTest extends \PHPUnit_Framework_TestCase
     private $conditionFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger | \PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface | \PHPUnit_Framework_MockObject_MockObject
      */
     private $loggerMock;
 
@@ -40,7 +40,7 @@ class CombineTest extends \PHPUnit_Framework_TestCase
             ->setMethods([])
             ->getMock();
 
-        $this->loggerMock = $this->getMockBuilder('\Magento\Framework\Logger')
+        $this->loggerMock = $this->getMockBuilder('\Psr\Log\LoggerInterface')
             ->disableOriginalConstructor()
             ->setMethods([])
             ->getMock();
@@ -111,7 +111,7 @@ class CombineTest extends \PHPUnit_Framework_TestCase
             ->willReturn($this->conditionObjectMock);
 
         $this->loggerMock->expects($this->never())
-            ->method('logException');
+            ->method('critical');
 
         $result = $this->combine->loadArray($array);
 
@@ -138,7 +138,7 @@ class CombineTest extends \PHPUnit_Framework_TestCase
             ->willThrowException(new \Exception('everything is fine, it is test'));
 
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with();
 
         $result = $this->combine->loadArray($array);
diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php
index 97289d77f0598c92a3f42df1faf45b58e14b4e62..93ad5f6f97d44e8b5012a8df2c51edb88bfa1173 100644
--- a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php
@@ -55,7 +55,7 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
 
     public function testValidateAttributeEqualCategoryId()
     {
-        $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false);
+        $product = $this->getMock('Magento\Framework\Model\AbstractModel', ["getAttribute"], [], '', false);
         $this->_condition->setAttribute('category_ids');
         $product->setAvailableInCategories(new \Magento\Framework\Object());
         $this->assertFalse($this->_condition->validate($product));
@@ -63,7 +63,16 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
 
     public function testValidateEmptyEntityAttributeValues()
     {
-        $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false);
+        $product = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ["getAttribute", 'getResource'],
+            [],
+            '',
+            false
+        );
+        $product->expects($this->once())
+            ->method('getResource')
+            ->willReturn(null);
         $product->setId(1);
         $configProperty = new \ReflectionProperty(
             'Magento\Rule\Model\Condition\Product\AbstractProduct',
@@ -76,7 +85,13 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
 
     public function testValidateEmptyEntityAttributeValuesWithResource()
     {
-        $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false);
+        $product = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ["getAttribute", 'getResource'],
+            [],
+            '',
+            false
+        );
         $product->setId(1);
         $time = '04/19/2012 11:59 am';
         $product->setData('someAttribute', $time);
@@ -103,8 +118,10 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
             ->with('someAttribute')
             ->will($this->returnValue($attribute));
         $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false);
+        $product->expects($this->atLeastOnce())
+            ->method('getResource')
+            ->willReturn($newResource);
 
-        $product->setResource($newResource);
         $this->assertFalse($this->_condition->validate($product));
 
         $product->setData('someAttribute', 'option1,option2,option3');
@@ -125,7 +142,13 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
     public function testValidateSetEntityAttributeValuesWithResource()
     {
         $this->_condition->setAttribute('someAttribute');
-        $product = $this->getMock('\Magento\Framework\Object', ['getAttribute'], [], '', false);
+        $product = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ['getAttribute', 'getResource'],
+            [],
+            '',
+            false
+        );
         $product->setAtribute('attribute');
         $product->setId(12);
 
@@ -146,7 +169,9 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($attribute));
         $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false);
 
-        $product->setResource($newResource);
+        $product->expects($this->atLeastOnce())
+            ->method('getResource')
+            ->willReturn($newResource);
 
         $this->_entityAttributeValuesProperty->setValue(
             $this->_condition,
@@ -161,7 +186,13 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
 
     public function testValidateSetEntityAttributeValuesWithoutResource()
     {
-        $product = $this->getMock('\Magento\Framework\Object', ['someMethod'], [], '', false);
+        $product = $this->getMock(
+            'Magento\Framework\Model\AbstractModel',
+            ['someMethod', 'getResource', 'load'],
+            [],
+            '',
+            false
+        );
         $this->_condition->setAttribute('someAttribute');
         $product->setAtribute('attribute');
         $product->setId(12);
@@ -198,7 +229,9 @@ class AbstractProductTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue($attribute));
         $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false);
 
-        $product->setResource($newResource);
+        $product->expects($this->atLeastOnce())
+            ->method('getResource')
+            ->willReturn($newResource);
 
         $this->_entityAttributeValuesProperty->setValue(
             $this->_condition,
diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Resource/Rule/Collection/AbstractCollectionTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Resource/Rule/Collection/AbstractCollectionTest.php
index f6aafa74b4ea419791e4a8aeada4cf959de0e722..5b0448f6cc93328262cdcb076218f1c4e63b6a3c 100644
--- a/dev/tests/unit/testsuite/Magento/Rule/Model/Resource/Rule/Collection/AbstractCollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Resource/Rule/Collection/AbstractCollectionTest.php
@@ -25,7 +25,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     protected $_entityFactoryMock;
 
     /**
-     * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_loggerMock;
 
@@ -47,7 +47,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->_entityFactoryMock = $this->getMock('Magento\Framework\Data\Collection\EntityFactoryInterface');
-        $this->_loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->_loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->_fetchStrategyMock = $this->getMock('Magento\Framework\Data\Collection\Db\FetchStrategyInterface');
         $this->_managerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
         $this->_db = $this->getMockForAbstractClass(
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..79deefa5c8c7908bc27408326e7911afff6ef7fe
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Block\Adminhtml\Order\Create;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+/**
+ * Totals block test
+ */
+class TotalsTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Sales\Block\Adminhtml\Order\Create\Totals
+     */
+    protected $totals;
+
+    /**
+     * @var \Magento\Sales\Model\Quote|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quoteMock;
+
+    /**
+     * @var \Magento\Backend\Model\Session\Quote|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $sessionQuoteMock;
+
+    protected function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+
+        $this->quoteMock = $this->getMock(
+            '\Magento\Sales\Model\Quote', ['getCustomerNoteNotify'], [], '', false
+        );
+        $this->sessionQuoteMock = $this->getMock(
+            '\Magento\Backend\Model\Session\Quote', [], [], '', false
+        );
+
+        $this->sessionQuoteMock->expects($this->any())
+            ->method('getQuote')
+            ->willReturn($this->quoteMock);
+
+        $this->totals = $this->objectManager->getObject(
+            '\Magento\Sales\Block\Adminhtml\Order\Create\Totals',
+            [
+                'sessionQuote' => $this->sessionQuoteMock
+            ]
+        );
+    }
+
+    /**
+     * @param mixed $customerNoteNotify
+     * @param bool $expectedResult
+     * @dataProvider getNoteNotifyDataProvider
+     */
+    public function testGetNoteNotify($customerNoteNotify, $expectedResult)
+    {
+        $this->quoteMock->expects($this->any())
+            ->method('getCustomerNoteNotify')
+            ->willReturn($customerNoteNotify);
+
+        $this->assertEquals($expectedResult, $this->totals->getNoteNotify());
+    }
+
+    /**
+     * @return array
+     */
+    public function getNoteNotifyDataProvider()
+    {
+        return [
+            [0, false],
+            [1, true],
+            ['0', false],
+            ['1', true],
+            [null, true]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..28818895ef30c57dfce4c1b52c97890b5f5fc137
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Block\Adminhtml\Order\View\Tab\Stub;
+
+/**
+ * Stub for an online payment method
+ */
+class OnlineMethod extends \Magento\Payment\Model\Method\AbstractMethod
+{
+    /**
+     * Availability option
+     *
+     * @var bool
+     */
+    protected $_isOffline = false;
+}
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f82ea8b4220103e75002921f7e153b19ced441cc
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Sales\Block\Adminhtml\Order\View\Tab;
+
+/**
+ * Order transactions tab test
+ */
+class TransactionsTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Sales\Block\Adminhtml\Order\View\Tab\Transactions
+     */
+    protected $transactionsTab;
+
+    /**
+     * @var \Magento\Framework\Authorization|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $authorizationMock;
+
+    /**
+     * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $coreRegistryMock;
+
+    /**
+     * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $orderMock;
+
+    /**
+     * @var \Magento\Sales\Model\Order\Payment|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $paymentMock;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->authorizationMock = $this->getMock('\Magento\Framework\Authorization', [], [], '', false);
+        $this->coreRegistryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false);
+        $this->orderMock = $this->getMock('\Magento\Sales\Model\Order', [], [], '', false);
+        $this->paymentMock = $this->getMock('\Magento\Sales\Model\Order\Payment', [], [], '', false);
+
+        $this->coreRegistryMock->expects($this->any())
+            ->method('registry')
+            ->with('current_order')
+            ->willReturn($this->orderMock);
+
+        $this->orderMock->expects($this->any())
+            ->method('getPayment')
+            ->willReturn($this->paymentMock);
+
+        $this->transactionsTab = $this->objectManager->getObject(
+            'Magento\Sales\Block\Adminhtml\Order\View\Tab\Transactions',
+            [
+                'authorization' => $this->authorizationMock,
+                'registry' => $this->coreRegistryMock
+            ]
+        );
+    }
+
+    public function testGetOrder()
+    {
+        $this->assertInstanceOf('\Magento\Sales\Model\Order', $this->transactionsTab->getOrder());
+    }
+
+    /**
+     * @param string $methodClass
+     * @param bool $expectedResult
+     * @depends testGetOrder
+     * @dataProvider canShowTabDataProvider
+     */
+    public function testCanShowTab($methodClass, $expectedResult)
+    {
+        $methodInstance = $this->objectManager->getObject($methodClass);
+        $this->paymentMock->expects($this->any())
+            ->method('getMethodInstance')
+            ->willReturn($methodInstance);
+
+        $this->assertEquals($expectedResult, $this->transactionsTab->canShowTab());
+    }
+
+    /**
+     * @return array
+     */
+    public function canShowTabDataProvider()
+    {
+        return [
+            ['\Magento\Sales\Block\Adminhtml\Order\View\Tab\Stub\OnlineMethod', true],
+            ['\Magento\OfflinePayments\Model\Cashondelivery', false],
+            ['\Magento\OfflinePayments\Model\Checkmo', false],
+            ['\Magento\OfflinePayments\Model\Banktransfer', false],
+            ['\Magento\OfflinePayments\Model\Purchaseorder', false]
+        ];
+    }
+
+    /**
+     * @param bool $isAllowed
+     * @param bool $expectedResult
+     * @dataProvider isHiddenDataProvider
+     */
+    public function testIsHidden($isAllowed, $expectedResult)
+    {
+        $this->authorizationMock->expects($this->any())
+            ->method('isAllowed')
+            ->with('Magento_Sales::transactions_fetch')
+            ->willReturn($isAllowed);
+
+        $this->assertEquals($expectedResult, $this->transactionsTab->isHidden());
+    }
+
+    /**
+     * @return array
+     */
+    public function isHiddenDataProvider()
+    {
+        return [
+            [true, false],
+            [false, true]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php
index 4594b959c67b0fb443bc8804ab1095985580733b..80a1d4554f53572aee23c41bd576bb1cd3f10dba 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php
@@ -83,7 +83,7 @@ class CreateTest extends \PHPUnit_Framework_TestCase
         $registryMock = $this->getMock('Magento\Framework\Registry');
         $configMock = $this->getMock('Magento\Sales\Model\Config', [], [], '', false);
         $this->sessionQuoteMock = $this->getMock('Magento\Backend\Model\Session\Quote', [], [], '', false);
-        $loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $copyMock = $this->getMock('Magento\Framework\Object\Copy', [], [], '', false);
         $messageManagerMock = $this->getMock('Magento\Framework\Message\ManagerInterface');
         $this->formFactoryMock = $this->getMock(
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/EmailSenderTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/EmailSenderTest.php
index b8003b302be29e50960cc195903ac142d7f37371..36eb38f6789a81f524ded30e60fdb52b1e254979 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/EmailSenderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/AdminOrder/EmailSenderTest.php
@@ -41,7 +41,7 @@ class EmailSenderTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->loggerMock = $this->getMock(
-            '\Magento\Framework\Logger',
+            '\Psr\Log\LoggerInterface',
             [],
             [],
             '',
@@ -80,7 +80,7 @@ class EmailSenderTest extends \PHPUnit_Framework_TestCase
         $this->messageManagerMock->expects($this->once())
             ->method('addWarning');
         $this->loggerMock->expects($this->once())
-            ->method('logException');
+            ->method('critical');
 
         $this->assertFalse($this->emailSender->send($this->orderMock));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/CreditmemoNotifierTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/CreditmemoNotifierTest.php
index 7eb45cfe80f8c5e9de67352f9036a3f3a8eb6f5d..02507357841a117db6297bf0ba77b7af85d41515 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/CreditmemoNotifierTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/CreditmemoNotifierTest.php
@@ -61,13 +61,7 @@ class CreditmemoNotifierTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException'],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->notifier = new CreditmemoNotifier(
             $this->historyCollectionFactory,
             $this->loggerMock,
@@ -139,7 +133,7 @@ class CreditmemoNotifierTest extends \PHPUnit_Framework_TestCase
             ->with($this->equalTo($this->creditmemo))
             ->will($this->throwException($exception));
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with($this->equalTo($exception));
         $this->assertFalse($this->notifier->notify($this->creditmemo));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/InvoiceNotifierTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/InvoiceNotifierTest.php
index b838e43bd80b02ca16d967be78b27c3429916e50..0c1e956462581c43b767ff3076c45aee590932fb 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/InvoiceNotifierTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/InvoiceNotifierTest.php
@@ -61,13 +61,7 @@ class InvoiceNotifierTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException'],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->notifier = new InvoiceNotifier(
             $this->historyCollectionFactory,
             $this->loggerMock,
@@ -139,7 +133,7 @@ class InvoiceNotifierTest extends \PHPUnit_Framework_TestCase
             ->with($this->equalTo($this->invoice))
             ->will($this->throwException($exception));
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with($this->equalTo($exception));
         $this->assertFalse($this->notifier->notify($this->invoice));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/Total/Config/BaseTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/Total/Config/BaseTest.php
index 9328efcab2f8c4badc0b8b68c5755a5b1f49df4e..2f75543c3981b7ee41770f2a302e4dd3316401e7 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/Order/Total/Config/BaseTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/Order/Total/Config/BaseTest.php
@@ -14,7 +14,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\App\Cache\Type\Config|\PHPUnit_Framework_MockObject_MockObject */
     protected $configCacheType;
 
-    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $logger;
 
     /** @var \Magento\Sales\Model\Config|\PHPUnit_Framework_MockObject_MockObject */
@@ -26,7 +26,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $this->configCacheType = $this->getMock('Magento\Framework\App\Cache\Type\Config', [], [], '', false);
-        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->salesConfig = $this->getMock('Magento\Sales\Model\Config', [], [], '', false);
         $this->orderTotalFactory = $this->getMock('Magento\Sales\Model\Order\TotalFactory', [], [], '', false);
 
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderNotifierTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderNotifierTest.php
index c915ea7ec5c556ac06d076fbca992b74b794c3cd..b9e83c91494593beda174d2b98b85f7d2b29d936 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderNotifierTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderNotifierTest.php
@@ -61,13 +61,7 @@ class OrderNotifierTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException'],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->notifier = new OrderNotifier(
             $this->historyCollectionFactory,
             $this->loggerMock,
@@ -139,7 +133,7 @@ class OrderNotifierTest extends \PHPUnit_Framework_TestCase
             ->with($this->equalTo($this->order))
             ->will($this->throwException($exception));
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with($this->equalTo($exception));
         $this->assertFalse($this->notifier->notify($this->order));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php
index 17e91454fa8cdab23e95d7c8fc8f49d868e3a814..6af26f5a8165ff5d41b2ca92cd10dbe50ee0ae12 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php
@@ -4,6 +4,8 @@
  */
 namespace Magento\Sales\Model;
 
+use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory as HistoryCollectionFactory;
+
 /**
  * Test class for \Magento\Sales\Model\Order
  */
@@ -39,6 +41,11 @@ class OrderTest extends \PHPUnit_Framework_TestCase
      */
     protected $item;
 
+    /**
+     * @var HistoryCollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $historyCollectionFactoryMock;
+
     protected function setUp()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
@@ -56,6 +63,13 @@ class OrderTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $this->historyCollectionFactoryMock = $this->getMock(
+            'Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory',
+            ['create'],
+            [],
+            '',
+            false
+        );
         $this->item = $this->getMock(
             'Magento\Sales\Model\Resource\Order\Item',
             ['isDeleted', 'getQtyToInvoice', 'getParentItemId', 'getQuoteItemId'],
@@ -87,7 +101,8 @@ class OrderTest extends \PHPUnit_Framework_TestCase
                 'paymentCollectionFactory' => $this->paymentCollectionFactoryMock,
                 'orderItemCollectionFactory' => $this->orderItemCollectionFactoryMock,
                 'data' => ['increment_id' => $this->incrementId],
-                'context' => $context
+                'context' => $context,
+                'historyCollectionFactory' => $this->historyCollectionFactoryMock
             ]
         );
     }
@@ -484,4 +499,70 @@ class OrderTest extends \PHPUnit_Framework_TestCase
     {
         $this->assertEquals('order', $this->order->getEntityType());
     }
+
+    /**
+     * Run test getStatusHistories method
+     *
+     * @return void
+     */
+    public function testGetStatusHistories()
+    {
+        $itemMock = $this->getMockForAbstractClass(
+            'Magento\Sales\Api\Data\OrderStatusHistoryInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['setOrder']
+        );
+        $dbMock = $this->getMock(
+            'Magento\Framework\Data\Collection\Db',
+            ['setOrder'],
+            [],
+            '',
+            false
+        );
+        $collectionMock = $this->getMock(
+            'Magento\Sales\Model\Resource\Order\Status\History\Collection',
+            [
+                'setOrderFilter',
+                'setOrder',
+                'getItems',
+                'getIterator',
+                'toOptionArray',
+                'count',
+                'load'
+            ],
+            [],
+            '',
+            false
+        );
+
+        $collectionItems = [$itemMock];
+
+        $collectionMock->expects($this->once())
+            ->method('setOrderFilter')
+            ->with($this->order)
+            ->willReturnSelf();
+        $collectionMock->expects($this->once())
+            ->method('setOrder')
+            ->with('created_at', 'desc')
+            ->willReturn($dbMock);
+        $dbMock->expects($this->once())
+            ->method('setOrder')
+            ->with('entity_id', 'desc')
+            ->willReturn($collectionMock);
+        $collectionMock->expects($this->once())
+            ->method('getItems')
+            ->willReturn($collectionItems);
+
+        $this->historyCollectionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($collectionMock);
+
+        for ($i = 10; --$i;) {
+            $this->assertEquals($collectionItems, $this->order->getStatusHistories());
+        }
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/Quote/Address/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/Quote/Address/ValidatorTest.php
index d73cf5246be7226c0d2007c5dfcbbb5882824db2..5f65333e6460d09f7c02b14ebdb07d17c940389b 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/Quote/Address/ValidatorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/Quote/Address/ValidatorTest.php
@@ -46,7 +46,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
             ->method('create')
             ->will($this->returnValue($this->countryMock));
         $this->model = $objectManager->getObject(
-            '\Magento\Sales\Model\Quote\Address\Validator',
+            'Magento\Sales\Model\Quote\Address\Validator',
             [
                 'countryFactory' => $this->countryFactoryMock,
             ]
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/Resource/Order/Status/History/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/Resource/Order/Status/History/CollectionTest.php
index 7d76ae4ca3bec025d59ad18f01c33c17b1fd06fb..27daafea1a9712cad1d458d26be64d821f14b484 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Model/Resource/Order/Status/History/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Model/Resource/Order/Status/History/CollectionTest.php
@@ -97,7 +97,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             ->method('create')
             ->will($this->returnValue($this->historyItemMock));
 
-        $logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $logger = $this->getMock('Psr\Log\LoggerInterface');
         $this->collection = new \Magento\Sales\Model\Resource\Order\Status\History\Collection(
             $this->entityFactoryMock,
             $logger,
diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/Resource/Report/CollectionTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/Resource/Report/CollectionTest.php
index bd0aa76837deb4a8e014cb7a91d0fd315d01e192..25e0312732b58c975e2ddcad37914e1cd2a3c582 100644
--- a/dev/tests/unit/testsuite/Magento/SalesRule/Model/Resource/Report/CollectionTest.php
+++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/Resource/Report/CollectionTest.php
@@ -61,13 +61,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             false
         );
 
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            [],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->fetchStrategy = $this->getMock(
             'Magento\Framework\Data\Collection\Db\FetchStrategyInterface',
diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php
index bc875f4835b177b4cd8f2ce1e657c20c3fdd703e..200e619dbfcbed2678ce3ae894a762c019289a84 100644
--- a/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php
+++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php
@@ -58,10 +58,16 @@ class RulesApplierTest extends \PHPUnit_Framework_TestCase
         );
     }
 
-    public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed()
+    /**
+     * @param bool $isChildren
+     * @param bool $isContinue
+     *
+     * @dataProvider dataProviderChildren
+     */
+    public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed($isChildren, $isContinue)
     {
         $positivePrice = 1;
-        $skipValidation = true;
+        $skipValidation = false;
         $item = $this->getPreparedItem();
         $couponCode = 111;
 
@@ -73,7 +79,7 @@ class RulesApplierTest extends \PHPUnit_Framework_TestCase
          */
         $ruleWithStopFurtherProcessing = $this->getMock(
             'Magento\SalesRule\Model\Rule',
-            ['getStoreLabel', 'getCouponType', 'getRuleId', '__wakeup'],
+            ['getStoreLabel', 'getCouponType', 'getRuleId', '__wakeup', 'getActions'],
             [],
             '',
             false
@@ -87,6 +93,14 @@ class RulesApplierTest extends \PHPUnit_Framework_TestCase
             false
         );
 
+        $actionMock = $this->getMock(
+            'Magento\Rule\Model\Action\Collection',
+            ['validate'],
+            [],
+            '',
+            false
+        );
+
         $ruleWithStopFurtherProcessing->setName('ruleWithStopFurtherProcessing');
         $ruleThatShouldNotBeRun->setName('ruleThatShouldNotBeRun');
         $rules = [$ruleWithStopFurtherProcessing, $ruleThatShouldNotBeRun];
@@ -96,20 +110,52 @@ class RulesApplierTest extends \PHPUnit_Framework_TestCase
 
         $this->validatorUtility->expects($this->atLeastOnce())
             ->method('canProcessRule')
-            ->will(
-                $this->returnValue(true)
-            );
-        $ruleWithStopFurtherProcessing->expects($this->any())
-            ->method('getRuleId')
-            ->will($this->returnValue($ruleId));
-        $this->applyRule($item, $ruleWithStopFurtherProcessing);
-        $ruleWithStopFurtherProcessing->setStopRulesProcessing(true);
-        $ruleThatShouldNotBeRun->expects($this->never())
-            ->method('getStopRulesProcessing');
+            ->will($this->returnValue(true));
+
+        $ruleWithStopFurtherProcessing->expects($this->atLeastOnce())
+            ->method('getActions')
+            ->willReturn($actionMock);
+        $actionMock->expects($this->at(0))
+            ->method('validate')
+            ->with($item)
+            ->willReturn(!$isChildren);
+
+        // if there are child elements, check them
+        if ($isChildren) {
+            $item->expects($this->atLeastOnce())
+                ->method('getChildren')
+                ->willReturn([$item]);
+            $actionMock->expects($this->at(1))
+                ->method('validate')
+                ->with($item)
+                ->willReturn(!$isContinue);
+        }
+
+        //
+        if (!$isContinue || !$isChildren) {
+            $ruleWithStopFurtherProcessing->expects($this->any())
+                ->method('getRuleId')
+                ->will($this->returnValue($ruleId));
+
+            $this->applyRule($item, $ruleWithStopFurtherProcessing);
+
+            $ruleWithStopFurtherProcessing->setStopRulesProcessing(true);
+            $ruleThatShouldNotBeRun->expects($this->never())
+                ->method('getStopRulesProcessing');
+        }
+
         $result = $this->rulesApplier->applyRules($item, $rules, $skipValidation, $couponCode);
         $this->assertEquals($appliedRuleIds, $result);
     }
 
+    public function dataProviderChildren()
+    {
+        return [
+            ['isChildren' => true, 'isContinue' => false],
+            ['isChildren' => false, 'isContinue' => true],
+        ];
+    }
+
     /**
      * @return \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -137,7 +183,8 @@ class RulesApplierTest extends \PHPUnit_Framework_TestCase
                 'setDiscountPercent',
                 'getAddress',
                 'setAppliedRuleIds',
-                '__wakeup'
+                '__wakeup',
+                'getChildren'
             ],
             [],
             '',
diff --git a/dev/tests/unit/testsuite/Magento/Search/Model/DataProviderTest.php b/dev/tests/unit/testsuite/Magento/Search/Model/DataProviderTest.php
index 402783398b25db23bc57a75560326940c8ce81ee..e5293d8bc0174e6548de2005798154c2df90cbc7 100644
--- a/dev/tests/unit/testsuite/Magento/Search/Model/DataProviderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Search/Model/DataProviderTest.php
@@ -24,14 +24,14 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase
         /** @var \Magento\Search\Model\QueryInterface|\PHPUnit_Framework_MockObject_MockObject $searchQuery */
         $searchQuery = $this->getMockBuilder('\Magento\Search\Model\QueryInterface')->getMockForAbstractClass();
         /** @var \Magento\Search\Model\SearchDataProvider $dataProvider */
-        $dataProvider = $this->objectManager->getObject('\Magento\Search\Model\SearchDataProvider');
+        $dataProvider = $this->objectManager->getObject('Magento\Search\Model\SearchDataProvider');
         $this->assertEquals([], $dataProvider->getSearchData($searchQuery));
     }
 
     public function testIsCountResultsEnabled()
     {
         /** @var \Magento\Search\Model\SearchDataProvider $dataProvider */
-        $dataProvider = $this->objectManager->getObject('\Magento\Search\Model\SearchDataProvider');
+        $dataProvider = $this->objectManager->getObject('Magento\Search\Model\SearchDataProvider');
         $this->assertFalse($dataProvider->isCountResultsEnabled());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Search/Model/QueryResultTest.php b/dev/tests/unit/testsuite/Magento/Search/Model/QueryResultTest.php
index d9f3f429ca503a86b586e9bba7ee60326b1f950e..16c75ce01c82edecfc83e0992fedcfacba174dc3 100644
--- a/dev/tests/unit/testsuite/Magento/Search/Model/QueryResultTest.php
+++ b/dev/tests/unit/testsuite/Magento/Search/Model/QueryResultTest.php
@@ -26,7 +26,7 @@ class QueryResultTest extends \PHPUnit_Framework_TestCase
     {
         /** @var \Magento\Search\Model\QueryResult $queryResult */
         $queryResult = $this->objectManager->getObject(
-            '\Magento\Search\Model\QueryResult',
+            'Magento\Search\Model\QueryResult',
             [
                 'queryText' => $queryText,
                 'resultsCount' => $resultsCount,
diff --git a/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabelTest.php b/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabelTest.php
index 4f137b020f68a80d62a967ad41f6c50ac7f4097c..3f95683d565f335e7bf90081728663ee8a7d67d2 100644
--- a/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/CreateLabelTest.php
@@ -199,13 +199,7 @@ class CreateLabelTest extends \PHPUnit_Framework_TestCase
      */
     public function testExecuteSaveException()
     {
-        $logerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException', '__wakeup'],
-            [],
-            '',
-            false
-        );
+        $logerMock = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->shipmentLoaderMock->expects($this->once())
             ->method('load')
@@ -215,10 +209,10 @@ class CreateLabelTest extends \PHPUnit_Framework_TestCase
             ->with($this->shipmentMock, $this->requestMock)
             ->will($this->returnValue(true));
         $this->shipmentMock->expects($this->once())->method('save')->will($this->throwException(new \Exception()));
-        $logerMock->expects($this->once())->method('logException');
+        $logerMock->expects($this->once())->method('critical');
         $this->objectManagerMock->expects($this->once())
             ->method('get')
-            ->with('Magento\Framework\Logger')
+            ->with('Psr\Log\LoggerInterface')
             ->will($this->returnValue($logerMock));
         $this->responseMock->expects($this->once())->method('representJson');
 
diff --git a/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabelTest.php b/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabelTest.php
index 87df1bed2da2b3cfc51b1d625ec3bd7ccb2a2303..441744207973257fdcb5a1e90c2d042ecea689b8 100644
--- a/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Shipping/Controller/Adminhtml/Order/Shipment/PrintLabelTest.php
@@ -301,13 +301,7 @@ class PrintLabelTest extends \PHPUnit_Framework_TestCase
         $labelContent = 'Label-content';
         $incrementId = '1000001';
 
-        $loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException'],
-            [],
-            '',
-            false
-        );
+        $loggerMock = $this->getMock('Psr\Log\LoggerInterface');
 
         $this->shipmentLoaderMock->expects($this->once())
             ->method('load')
@@ -332,10 +326,10 @@ class PrintLabelTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnSelf());
         $this->objectManagerMock->expects($this->once())
             ->method('get')
-            ->with('Magento\Framework\Logger')
+            ->with('Psr\Log\LoggerInterface')
             ->will($this->returnValue($loggerMock));
         $loggerMock->expects($this->once())
-            ->method('logException');
+            ->method('critical');
         $this->requestMock->expects($this->at(4))
             ->method('getParam')
             ->with('shipment_id')
diff --git a/dev/tests/unit/testsuite/Magento/Shipping/Model/ShipmentNotifierTest.php b/dev/tests/unit/testsuite/Magento/Shipping/Model/ShipmentNotifierTest.php
index c37df83ef1992681e3b3c152835b797ea75608b2..647d012cb2e424886120a521d45534d2c1f35f9b 100644
--- a/dev/tests/unit/testsuite/Magento/Shipping/Model/ShipmentNotifierTest.php
+++ b/dev/tests/unit/testsuite/Magento/Shipping/Model/ShipmentNotifierTest.php
@@ -61,13 +61,7 @@ class ShipmentNotifierTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->loggerMock = $this->getMock(
-            'Magento\Framework\Logger',
-            ['logException'],
-            [],
-            '',
-            false
-        );
+        $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface');
         $this->notifier = new ShipmentNotifier(
             $this->historyCollectionFactory,
             $this->loggerMock,
@@ -139,7 +133,7 @@ class ShipmentNotifierTest extends \PHPUnit_Framework_TestCase
             ->with($this->equalTo($this->shipment))
             ->will($this->throwException($exception));
         $this->loggerMock->expects($this->once())
-            ->method('logException')
+            ->method('critical')
             ->with($this->equalTo($exception));
         $this->assertFalse($this->notifier->notify($this->shipment));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Store/Model/StorageFactoryTest.php b/dev/tests/unit/testsuite/Magento/Store/Model/StorageFactoryTest.php
index 40baf58ed1c8151caf9ec7e4777df69111b34b2e..636081c0a109cde433cb320f8b1a291812eece7c 100644
--- a/dev/tests/unit/testsuite/Magento/Store/Model/StorageFactoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Store/Model/StorageFactoryTest.php
@@ -119,7 +119,6 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->_logMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
         $this->_sidResolverMock = $this->getMock(
             '\Magento\Framework\Session\SidResolverInterface',
             [],
@@ -135,10 +134,9 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
         $this->_scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
         $this->request = $this->getMock('Magento\Framework\App\RequestInterface', [], [], '', false);
 
-        $this->_model = $this->helper->getObject('\Magento\Store\Model\StorageFactory', [
+        $this->_model = $this->helper->getObject('Magento\Store\Model\StorageFactory', [
             'objectManager' => $this->_objectManagerMock,
             'eventManager' => $this->_eventManagerMock,
-            'logger' => $this->_logMock,
             'sidResolver' => $this->_sidResolverMock,
             'appState' => $this->_appStateMock,
             'httpContext' => $this->_httpContext,
@@ -183,7 +181,7 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
     {
         $store = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
 
-        $this->_storeManager->expects($this->exactly(3))->method('getStore')->will($this->returnValue($store));
+        $this->_storeManager->expects($this->exactly(2))->method('getStore')->will($this->returnValue($store));
 
         $this->_scopeConfig->expects(
             $this->at(0)
@@ -196,17 +194,6 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
             $this->returnValue(true)
         );
 
-        $this->_scopeConfig->expects(
-            $this->at(1)
-        )->method(
-            'isSetFlag'
-        )->with(
-            'dev/log/active',
-            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
-        )->will(
-            $this->returnValue(true)
-        );
-
         $this->_objectManagerMock->expects(
             $this->once()
         )->method(
@@ -225,8 +212,6 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
             'core_app_init_current_store_after'
         );
 
-        $this->_logMock->expects($this->once())->method('unsetLoggers');
-        $this->_logMock->expects($this->exactly(2))->method('addStreamLog');
 
         $this->_sidResolverMock->expects($this->once())->method('setUseSessionInUrl')->with(true);
 
@@ -255,7 +240,6 @@ class StorageFactoryTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_eventManagerMock->expects($this->never())->method('dispatch');
-        $this->_logMock->expects($this->never())->method('initForStore');
         $this->_sidResolverMock->expects($this->never())->method('setUseSessionInUrl');
 
         /** test create instance */
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Block/Adminhtml/Items/Price/RendererTest.php b/dev/tests/unit/testsuite/Magento/Tax/Block/Adminhtml/Items/Price/RendererTest.php
index 18c10bb1d60bd4b5d61012cede09632e400415d6..5b3d9405babc3dd864adc053dfd7f0b344547ae5 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Block/Adminhtml/Items/Price/RendererTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Block/Adminhtml/Items/Price/RendererTest.php
@@ -46,7 +46,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->renderer = $objectManager->getObject(
-            '\Magento\Tax\Block\Adminhtml\Items\Price\Renderer',
+            'Magento\Tax\Block\Adminhtml\Items\Price\Renderer',
             [
                 'itemPriceRenderer' => $this->itemPriceRenderer,
                 'defaultColumnRenderer' => $this->defaultColumnRenderer,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Cart/Sidebar/TotalsTest.php b/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Cart/Sidebar/TotalsTest.php
index 6ffa098284da3da80c5cab36dc1e7251ebfec193..ae4eb2b7d0e88b7bfddb62b7fd36b927acbdbef9 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Cart/Sidebar/TotalsTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Cart/Sidebar/TotalsTest.php
@@ -62,7 +62,7 @@ class TotalsTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->totalsObj = $objectManager->getObject(
-            '\Magento\Tax\Block\Checkout\Cart\Sidebar\Totals',
+            'Magento\Tax\Block\Checkout\Cart\Sidebar\Totals',
             [
                 'checkoutSession' => $checkoutSession,
                 'taxHelper' => $this->taxHelper,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Shipping/PriceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Shipping/PriceTest.php
index 7015ba9a35ed1b9175b5b348d88ce7f2093b4619..c40596a3f0446310d3e0a4f09dc5c7dd74c5710c 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Shipping/PriceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Block/Checkout/Shipping/PriceTest.php
@@ -68,7 +68,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->priceObj = $objectManager->getObject(
-            '\Magento\Tax\Block\Checkout\Shipping\Price',
+            'Magento\Tax\Block\Checkout\Shipping\Price',
             [
                 'checkoutSession' => $checkoutSession,
                 'taxHelper' => $this->taxHelper,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Block/Item/Price/RendererTest.php b/dev/tests/unit/testsuite/Magento/Tax/Block/Item/Price/RendererTest.php
index 71da91647762815d31396bacd95e973d0b025960..c209104ed090bace5e5d2acfd37edee8215b3e6b 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Block/Item/Price/RendererTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Block/Item/Price/RendererTest.php
@@ -41,7 +41,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
             ->getMock();
 
         $this->renderer = $objectManager->getObject(
-            '\Magento\Tax\Block\Item\Price\Renderer',
+            'Magento\Tax\Block\Item\Price\Renderer',
             [
                 'taxHelper' => $this->taxHelper,
                 'priceCurrency' => $this->priceCurrency,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
index 90f95e6e632c7f4ccd6947647551f0762d6af6c4..4e6228bacccf730e0fa22c3e539637aa3b82d37a 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
@@ -97,7 +97,7 @@ class SubtotalTest extends \PHPUnit_Framework_TestCase
         $customerAddressRegionBuilderMock->expects($this->any())->method('setRegionId')->willReturnSelf();
 
         $this->model = $this->objectManager->getObject(
-            '\Magento\Tax\Model\Sales\Total\Quote\Subtotal',
+            'Magento\Tax\Model\Sales\Total\Quote\Subtotal',
             [
                 'taxConfig' => $this->taxConfigMock,
                 'taxCalculationService' => $this->taxCalculationMock,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php
index ae53fc86aff0f26875972cf36e422895efba5548..cc67af4a7cf0a00c8e2a8eb8f873779fdef5b768 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php
@@ -415,7 +415,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new ObjectManager($this);
         $taxTotalsCalcModel = $objectManager->getObject(
-            '\Magento\Tax\Model\Sales\Total\Quote\Tax',
+            'Magento\Tax\Model\Sales\Total\Quote\Tax',
             ['taxData' => $taxData]
         );
         $array = $taxTotalsCalcModel->processConfigArray([], null);
@@ -448,7 +448,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase
     public function testMapQuoteExtraTaxables($itemData, $addressData)
     {
         $objectManager = new ObjectManager($this);
-        $taxTotalsCalcModel = $objectManager->getObject('\Magento\Tax\Model\Sales\Total\Quote\Tax');
+        $taxTotalsCalcModel = $objectManager->getObject('Magento\Tax\Model\Sales\Total\Quote\Tax');
 
         $taxClassKeyBuilder = $this->getMockBuilder('\Magento\Tax\Api\Data\TaxClassKeyDataBuilder')
             ->disableOriginalConstructor()
@@ -606,7 +606,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new ObjectManager($this);
         $taxTotalsCalcModel = $objectManager->getObject(
-            '\Magento\Tax\Model\Sales\Total\Quote\Tax',
+            'Magento\Tax\Model\Sales\Total\Quote\Tax',
             ['taxConfig' => $taxConfig]
         );
 
@@ -695,7 +695,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase
     public function testGetLabel()
     {
         $objectManager = new ObjectManager($this);
-        $taxTotalsCalcModel = $objectManager->getObject('\Magento\Tax\Model\Sales\Total\Quote\Tax');
+        $taxTotalsCalcModel = $objectManager->getObject('Magento\Tax\Model\Sales\Total\Quote\Tax');
         $this->assertSame($taxTotalsCalcModel->getLabel(), __('Tax'));
     }
 
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxCalculationTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxCalculationTest.php
index 50084d96e69292ff5f8d9ee9881bc85aa15c55aa..3c1574c4186271eb37e60fb3366a3bee64150c80 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxCalculationTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxCalculationTest.php
@@ -79,7 +79,7 @@ class TaxCalculationTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = new ObjectManager($this);
         $this->taxCalculationService = $objectManager->getObject(
-            '\Magento\Tax\Model\TaxCalculation',
+            'Magento\Tax\Model\TaxCalculation',
             [
                 'calculation' => $this->calculationTool,
                 'calculatorFactory' => $this->calculatorFactory,
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2787e1c44c582e7280ca89617c703b9bd351bbfe
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+namespace Magento\Tax\Model\TaxClass\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class CustomerTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Tax\Api\TaxClassRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $taxClassRepositoryMock;
+
+    /**
+     * @var \Magento\Framework\Api\SearchCriteriaBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $searchCriteriaBuilderMock;
+
+    /**
+     * @var \Magento\Framework\Api\FilterBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $filterBuilderMock;
+
+    /**
+     * @var \Magento\Tax\Model\TaxClass\Source\Customer
+     */
+    protected $customer;
+
+    /**
+     * @var ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * Set up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+
+        $this->taxClassRepositoryMock = $this->getMockForAbstractClass(
+            'Magento\Tax\Api\TaxClassRepositoryInterface',
+            ['getList'],
+            '',
+            false,
+            true,
+            true,
+            []
+        );
+        $this->searchCriteriaBuilderMock = $this->getMock(
+            'Magento\Framework\Api\SearchCriteriaBuilder',
+            ['addFilter', 'create'],
+            [],
+            '',
+            false
+        );
+        $this->filterBuilderMock = $this->getMock(
+            'Magento\Framework\Api\FilterBuilder',
+            ['setField', 'setValue', 'create'],
+            [],
+            '',
+            false
+        );
+
+        $this->customer = $this->objectManager->getObject(
+            'Magento\Tax\Model\TaxClass\Source\Customer',
+            [
+                'taxClassRepository' => $this->taxClassRepositoryMock,
+                'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
+                'filterBuilder' => $this->filterBuilderMock
+            ]
+        );
+    }
+
+    /**
+     * Run test getAllOptions method
+     *
+     * @param bool $isEmpty
+     * @param array $expected
+     * @dataProvider dataProviderGetAllOptions
+     */
+    public function testGetAllOptions($isEmpty, array $expected)
+    {
+        $filterMock = $this->getMock(
+            'Magento\Framework\Api\Filter',
+            [],
+            [],
+            '',
+            false
+        );
+        $searchCriteriaMock = $this->getMock(
+            'Magento\Framework\Api\SearchCriteria',
+            [],
+            [],
+            '',
+            false
+        );
+        $searchResultsMock = $this->getMockForAbstractClass(
+            'Magento\Tax\Api\Data\TaxClassSearchResultsInterface',
+            [],
+            '',
+            false,
+            true,
+            true,
+            ['getItems']
+        );
+        $taxClassMock = $this->getMockForAbstractClass(
+            'Magento\Tax\Api\Data\TaxClassInterface',
+            ['getClassId', 'getClassName'],
+            '',
+            false,
+            true,
+            true
+        );
+
+        $this->filterBuilderMock->expects($this->once())
+            ->method('setField')
+            ->with(\Magento\Tax\Api\Data\TaxClassInterface::KEY_TYPE)
+            ->willReturnSelf();
+        $this->filterBuilderMock->expects($this->once())
+            ->method('setValue')
+            ->with(\Magento\Tax\Api\TaxClassManagementInterface::TYPE_CUSTOMER)
+            ->willReturnSelf();
+        $this->filterBuilderMock->expects($this->once())
+            ->method('create')
+            ->willReturn($filterMock);
+        $this->searchCriteriaBuilderMock->expects($this->once())
+            ->method('addFilter')
+            ->with([$filterMock])
+            ->willReturnSelf();
+        $this->searchCriteriaBuilderMock->expects($this->once())
+            ->method('create')
+            ->willReturn($searchCriteriaMock);
+        $this->taxClassRepositoryMock->expects($this->once())
+            ->method('getList')
+            ->with($searchCriteriaMock)
+            ->willReturn($searchResultsMock);
+
+        if (!$isEmpty) {
+            $taxClassMock->expects($this->once())
+                ->method('getClassId')
+                ->willReturn(10);
+            $taxClassMock->expects($this->once())
+                ->method('getClassName')
+                ->willReturn('class-name');
+
+            $items = [$taxClassMock];
+            $searchResultsMock->expects($this->once())
+                ->method('getItems')
+                ->willReturn($items);
+
+            // checking of a lack of re-initialization
+            for ($i = 10; --$i;) {
+                $result = $this->customer->getAllOptions();
+                $this->assertEquals($expected, $result);
+            }
+        } else {
+            $items = [];
+            $searchResultsMock->expects($this->once())
+                ->method('getItems')
+                ->willReturn($items);
+            // checking exception
+            $this->assertEmpty($this->customer->getAllOptions());
+        }
+    }
+
+    /**
+     * Data provider for testGetAllOptions
+     *
+     * @return array
+     */
+    public function dataProviderGetAllOptions()
+    {
+        return [
+            ['isEmpty' => false, 'expected' => [['value' => 10, 'label' => 'class-name']]],
+            ['isEmpty' => true, 'expected' => []]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Type/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Type/CustomerTest.php
index ca34e808ece7877f08e80d7274415e7054fa0b7a..bf76b0be065eb1146aa345772996153cbd19a931 100644
--- a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Type/CustomerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Type/CustomerTest.php
@@ -19,9 +19,9 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(['randomValue']));
 
         $filterBuilder = $objectManagerHelper
-            ->getObject('\Magento\Framework\Api\FilterBuilder');
+            ->getObject('Magento\Framework\Api\FilterBuilder');
         $filterGroupBuilder = $objectManagerHelper
-            ->getObject('\Magento\Framework\Api\Search\FilterGroupBuilder');
+            ->getObject('Magento\Framework\Api\Search\FilterGroupBuilder');
         $searchCriteriaBuilder = $objectManagerHelper->getObject(
             'Magento\Framework\Api\SearchCriteriaBuilder',
             [
diff --git a/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/IndexTest.php b/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/IndexTest.php
index 22b22e760544a397b4cd8117a28f209c8f117e43..bc70b77601ccc832cd892d5be404ed2555bd6748 100644
--- a/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/IndexTest.php
+++ b/dev/tests/unit/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Theme/IndexTest.php
@@ -17,7 +17,7 @@ class IndexTest extends \Magento\Theme\Controller\Adminhtml\System\Design\ThemeT
         $menuModel = $this->getMock(
             'Magento\Backend\Model\Menu',
             [],
-            [$this->getMock('Magento\Framework\Logger', [], [], '', false)]
+            [$this->getMock('Psr\Log\LoggerInterface')]
         );
         $menuModel->expects($this->once())
             ->method('getParentItems')
diff --git a/dev/tests/unit/testsuite/Magento/Tools/View/Deployer/LogTest.php b/dev/tests/unit/testsuite/Magento/Tools/View/Deployer/LogTest.php
index 46eecc68c7c9fb9e54cfd3c2e8ff9dc2a5829e2b..d5f0549c391342cdfd76185def6bf87740481751 100644
--- a/dev/tests/unit/testsuite/Magento/Tools/View/Deployer/LogTest.php
+++ b/dev/tests/unit/testsuite/Magento/Tools/View/Deployer/LogTest.php
@@ -5,8 +5,6 @@
 
 namespace Magento\Tools\View\Deployer;
 
-use Magento\Tools\View\Deployer\Log;
-
 class LogTest extends \PHPUnit_Framework_TestCase
 {
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Translation/Model/Inline/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Translation/Model/Inline/ConfigTest.php
index b4d125da73b928ceaf50b757ed8cfacd01099620..1dc15a6e778a90ea2434c1b01314ac7ece524213 100644
--- a/dev/tests/unit/testsuite/Magento/Translation/Model/Inline/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Translation/Model/Inline/ConfigTest.php
@@ -49,7 +49,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         );
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
         $config = $objectManager->getObject(
-            '\Magento\Translation\Model\Inline\Config',
+            'Magento\Translation\Model\Inline\Config',
             ['scopeConfig' => $scopeConfig]
         );
         $this->assertEquals($result, $config->isActive($store));
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Controller/ErrorProcessorTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Controller/ErrorProcessorTest.php
index 1411c2fc83efcdb39bb6c5f8b21994172d2d7c9f..58cd77c941e18c2def855fc7b064e466935edd05 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Controller/ErrorProcessorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Controller/ErrorProcessorTest.php
@@ -21,7 +21,7 @@ class ErrorProcessorTest extends \PHPUnit_Framework_TestCase
     /** @var \PHPUnit_Framework_MockObject_MockObject */
     protected $_appStateMock;
 
-    /** @var \Magento\Framework\Logger */
+    /** @var \Psr\Log\LoggerInterface */
     protected $_loggerMock;
 
     protected function setUp()
@@ -35,7 +35,7 @@ class ErrorProcessorTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->_loggerMock = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        $this->_loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
 
         $filesystemMock = $this->getMockBuilder('\Magento\Framework\Filesystem')
             ->disableOriginalConstructor()
@@ -198,7 +198,7 @@ class ErrorProcessorTest extends \PHPUnit_Framework_TestCase
     public function testMaskException($exception, $expectedHttpCode, $expectedMessage, $expectedDetails)
     {
         /** Assert that exception was logged. */
-        // TODO:MAGETWO-21077 $this->_loggerMock->expects($this->once())->method('logException');
+        // TODO:MAGETWO-21077 $this->_loggerMock->expects($this->once())->method('critical');
         $maskedException = $this->_errorProcessor->maskException($exception);
         $this->assertMaskedException(
             $maskedException,
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Controller/RequestTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Controller/RequestTest.php
index 6d3700564690eca4a69d12296967efde359db04d..493a58994d7235b3cabea59989b806a1ee0f42f3 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Controller/RequestTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Controller/RequestTest.php
@@ -29,7 +29,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
         $this->cookieReader = $this->getMock('Magento\Framework\Stdlib\Cookie\CookieReaderInterface');
 
         $this->request = $objectManager->getObject(
-            '\Magento\Webapi\Controller\Request',
+            'Magento\Webapi\Controller\Request',
             ['cookieReader' => $this->cookieReader]
         );
     }
@@ -46,4 +46,4 @@ class RequestTest extends \PHPUnit_Framework_TestCase
 
         $this->request->getCookie($key, $default);
     }
-} 
+}
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/ClassReflectorTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/ClassReflectorTest.php
index 30fdab7a8ccdc3841d89167a02f17f5838d08cff..498df37e372c3550fc957759b153d050ae2af8c0 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/ClassReflectorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/ClassReflectorTest.php
@@ -66,7 +66,9 @@ class ClassReflectorTest extends \PHPUnit_Framework_TestCase
     protected function _getSampleReflectionData()
     {
         return [
-            'documentation' => 'Basic random string generator',
+            'documentation' =>
+                'Basic random string generator. This line is short description '.
+                'This line is long description. This is still the long description.',
             'interface' => [
                 'in' => [
                     'parameters' => [
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/TestServiceForClassReflector.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/TestServiceForClassReflector.php
index f3f25ccb5f4a0b586a75481da0acf7a6a43f5567..cce8322bdafeac9b3fb818537d96d7590ec096f2 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/TestServiceForClassReflector.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/TestServiceForClassReflector.php
@@ -7,7 +7,10 @@ namespace Magento\Webapi\Model\Config;
 class TestServiceForClassReflector
 {
     /**
-     * Basic random string generator
+     * Basic random string generator. This line is short description
+     * This line is long description.
+     *
+     * This is still the long description.
      *
      * @param int $length length of the random string
      * @return string random string
diff --git a/dev/tests/unit/testsuite/Magento/Weee/Block/Item/Price/RendererTest.php b/dev/tests/unit/testsuite/Magento/Weee/Block/Item/Price/RendererTest.php
index af86ba438236e76645a6822fc4a3f15165716c98..b8facece366fca5254ea4fe3e20a5d4ca50e49dc 100644
--- a/dev/tests/unit/testsuite/Magento/Weee/Block/Item/Price/RendererTest.php
+++ b/dev/tests/unit/testsuite/Magento/Weee/Block/Item/Price/RendererTest.php
@@ -78,7 +78,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(self::STORE_ID));
 
         $this->renderer = $objectManager->getObject(
-            '\Magento\Weee\Block\Item\Price\Renderer',
+            'Magento\Weee\Block\Item\Price\Renderer',
             [
                 'weeeHelper' => $this->weeeHelper,
                 'priceCurrency' => $this->priceCurrency,
diff --git a/dev/tests/unit/testsuite/Magento/Wishlist/Controller/Index/CartTest.php b/dev/tests/unit/testsuite/Magento/Wishlist/Controller/Index/CartTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9fdcf260c8079805717df3610eb25a8fe4d0f91b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Wishlist/Controller/Index/CartTest.php
@@ -0,0 +1,797 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Wishlist\Controller\Index;
+
+class CartTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Cart
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $contextMock;
+
+    /**
+     * @var \Magento\Wishlist\Controller\WishlistProviderInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $wishlistProviderMock;
+
+    /**
+     * @var \Magento\Wishlist\Model\LocaleQuantityProcessor|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quantityProcessorMock;
+
+    /**
+     * @var \Magento\Wishlist\Model\ItemFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $itemFactoryMock;
+
+    /**
+     * @var \Magento\Checkout\Model\Cart|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $checkoutCartMock;
+
+    /**
+     * @var \Magento\Wishlist\Model\Item\OptionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $optionFactoryMock;
+
+    /**
+     * @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $productHelperMock;
+
+    /**
+     * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $escaperMock;
+
+    /**
+     * @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $helperMock;
+
+    /**
+     * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestMock;
+
+    /**
+     * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $responseMock;
+
+    /**
+     * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $redirectMock;
+
+    /**
+     * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManagerMock;
+
+    /**
+     * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $messageManagerMock;
+
+    /**
+     * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $urlMock;
+
+    protected function setUp()
+    {
+        $this->wishlistProviderMock = $this->getMockBuilder('Magento\Wishlist\Controller\WishlistProviderInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['getWishlist'])
+            ->getMockForAbstractClass();
+
+        $this->quantityProcessorMock = $this->getMockBuilder('Magento\Wishlist\Model\LocaleQuantityProcessor')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->itemFactoryMock = $this->getMockBuilder('Magento\Wishlist\Model\ItemFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->checkoutCartMock = $this->getMockBuilder('Magento\Checkout\Model\Cart')
+            ->disableOriginalConstructor()
+            ->setMethods(['save', 'getQuote', 'getShouldRedirectToCart', 'getCartUrl'])
+            ->getMock();
+
+        $this->optionFactoryMock = $this->getMockBuilder('Magento\Wishlist\Model\Item\OptionFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->productHelperMock = $this->getMockBuilder('Magento\Catalog\Helper\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->escaperMock = $this->getMockBuilder('Magento\Framework\Escaper')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->helperMock = $this->getMockBuilder('Magento\Wishlist\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->requestMock = $this->getMockBuilder('Magento\Framework\App\RequestInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['getParams', 'getParam'])
+            ->getMockForAbstractClass();
+
+        $this->responseMock = $this->getMockBuilder('Magento\Framework\App\ResponseInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['setRedirect'])
+            ->getMockForAbstractClass();
+
+        $this->redirectMock = $this->getMockBuilder('Magento\Framework\App\Response\RedirectInterface')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->messageManagerMock = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['addSuccess'])
+            ->getMockForAbstractClass();
+
+        $this->urlMock = $this->getMockBuilder('Magento\Framework\UrlInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['getUrl'])
+            ->getMockForAbstractClass();
+
+        $this->contextMock = $this->getMockBuilder('Magento\Framework\App\Action\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->contextMock->expects($this->any())
+            ->method('getRequest')
+            ->will($this->returnValue($this->requestMock));
+        $this->contextMock->expects($this->any())
+            ->method('getResponse')
+            ->will($this->returnValue($this->responseMock));
+        $this->contextMock->expects($this->any())
+            ->method('getRedirect')
+            ->will($this->returnValue($this->redirectMock));
+        $this->contextMock->expects($this->any())
+            ->method('getObjectManager')
+            ->will($this->returnValue($this->objectManagerMock));
+        $this->contextMock->expects($this->any())
+            ->method('getMessageManager')
+            ->will($this->returnValue($this->messageManagerMock));
+        $this->contextMock->expects($this->any())
+            ->method('getUrl')
+            ->will($this->returnValue($this->urlMock));
+
+        $this->model = new Cart(
+            $this->contextMock,
+            $this->wishlistProviderMock,
+            $this->quantityProcessorMock,
+            $this->itemFactoryMock,
+            $this->checkoutCartMock,
+            $this->optionFactoryMock,
+            $this->productHelperMock,
+            $this->escaperMock,
+            $this->helperMock
+        );
+    }
+
+    public function testExecuteWithNoItem()
+    {
+        $itemId = false;
+
+        $itemMock = $this->getMockBuilder('Magento\Wishlist\Model\Item')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('getId')
+            ->willReturn(null);
+
+        $this->redirectMock->expects($this->once())
+            ->method('redirect')
+            ->with($this->responseMock, '*/*', [])
+            ->willReturn($this->responseMock);
+
+        $this->assertEquals($this->responseMock, $this->model->execute());
+    }
+
+    public function testExecuteWithNoWishlist()
+    {
+        $itemId = 2;
+        $wishlistId = 1;
+
+        $itemMock = $this->getMockBuilder('Magento\Wishlist\Model\Item')
+            ->disableOriginalConstructor()
+            ->setMethods(['load', 'getId', 'getWishlistId'])
+            ->getMock();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('getId')
+            ->willReturn($itemId);
+        $itemMock->expects($this->once())
+            ->method('getWishlistId')
+            ->willReturn($wishlistId);
+
+        $this->wishlistProviderMock->expects($this->once())
+            ->method('getWishlist')
+            ->with($wishlistId)
+            ->willReturn(null);
+
+        $this->redirectMock->expects($this->once())
+            ->method('redirect')
+            ->with($this->responseMock, '*/*', [])
+            ->willReturn($this->responseMock);
+
+        $this->assertEquals($this->responseMock, $this->model->execute());
+    }
+
+    public function testExecuteWithQuantityArray()
+    {
+        $itemId = 2;
+        $wishlistId = 1;
+        $qty = [$itemId => 3];
+        $productId = 4;
+        $productName = 'product_name';
+        $indexUrl = 'index_url';
+        $configureUrl = 'configure_url';
+        $options = [5 => 'option'];
+        $params = ['item' => $itemId, 'qty' => $qty];
+        $refererUrl = 'referer_url';
+
+        $itemMock = $this->getMockBuilder('Magento\Wishlist\Model\Item')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'load',
+                    'getId',
+                    'getWishlistId',
+                    'setQty',
+                    'setOptions',
+                    'getBuyRequest',
+                    'mergeBuyRequest',
+                    'addToCart',
+                    'getProduct',
+                    'getProductId',
+                ]
+            )
+            ->getMock();
+
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->exactly(2))
+            ->method('getId')
+            ->willReturn($itemId);
+        $itemMock->expects($this->once())
+            ->method('getWishlistId')
+            ->willReturn($wishlistId);
+
+        $wishlistMock = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->wishlistProviderMock->expects($this->once())
+            ->method('getWishlist')
+            ->with($wishlistId)
+            ->willReturn($wishlistMock);
+
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('qty', null)
+            ->willReturn($qty);
+
+        $this->quantityProcessorMock->expects($this->once())
+            ->method('process')
+            ->with($qty[$itemId])
+            ->willReturnArgument(0);
+
+        $itemMock->expects($this->once())
+            ->method('setQty')
+            ->with($qty[$itemId])
+            ->willReturnSelf();
+
+        $this->urlMock->expects($this->at(0))
+            ->method('getUrl')
+            ->with('*/*', null)
+            ->willReturn($indexUrl);
+
+        $itemMock->expects($this->once())
+            ->method('getProductId')
+            ->willReturn($productId);
+
+        $this->urlMock->expects($this->at(1))
+            ->method('getUrl')
+            ->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId])
+            ->willReturn($configureUrl);
+
+        $optionMock = $this->getMockBuilder('Magento\Wishlist\Model\Item\Option')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($optionMock);
+
+        $optionsMock = $this->getMockBuilder('Magento\Wishlist\Model\Resource\Item\Option\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $optionMock->expects($this->once())
+            ->method('getCollection')
+            ->willReturn($optionsMock);
+
+        $optionsMock->expects($this->once())
+            ->method('addItemFilter')
+            ->with([$itemId])
+            ->willReturnSelf();
+        $optionsMock->expects($this->once())
+            ->method('getOptionsByItem')
+            ->with($itemId)
+            ->willReturn($options);
+
+        $itemMock->expects($this->once())
+            ->method('setOptions')
+            ->with($options)
+            ->willReturnSelf();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParams')
+            ->willReturn($params);
+
+        $buyRequestMock = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $itemMock->expects($this->once())
+            ->method('getBuyRequest')
+            ->willReturn($buyRequestMock);
+
+        $this->productHelperMock->expects($this->once())
+            ->method('addParamsToBuyRequest')
+            ->with($params, ['current_config' => $buyRequestMock])
+            ->willReturn($buyRequestMock);
+
+        $itemMock->expects($this->once())
+            ->method('mergeBuyRequest')
+            ->with($buyRequestMock)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('addToCart')
+            ->with($this->checkoutCartMock, true)
+            ->willReturn(true);
+
+        $this->checkoutCartMock->expects($this->once())
+            ->method('save')
+            ->willReturnSelf();
+
+        $quoteMock = $this->getMockBuilder('Magento\Sales\Model\Quote')
+            ->disableOriginalConstructor()
+            ->setMethods(['getHasError', 'collectTotals'])
+            ->getMock();
+
+        $this->checkoutCartMock->expects($this->exactly(2))
+            ->method('getQuote')
+            ->willReturn($quoteMock);
+
+        $quoteMock->expects($this->once())
+            ->method('collectTotals')
+            ->willReturnSelf();
+
+        $wishlistMock->expects($this->once())
+            ->method('save')
+            ->willReturnSelf();
+
+        $quoteMock->expects($this->once())
+            ->method('getHasError')
+            ->willReturn(false);
+
+        $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $itemMock->expects($this->once())
+            ->method('getProduct')
+            ->willReturn($productMock);
+
+        $productMock->expects($this->once())
+            ->method('getName')
+            ->willReturn($productName);
+
+        $this->escaperMock->expects($this->once())
+            ->method('escapeHtml')
+            ->with($productName, null)
+            ->willReturn($productName);
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addSuccess')
+            ->with('You added '  . $productName . ' to your shopping cart.', null)
+            ->willReturnSelf();
+
+        $this->checkoutCartMock->expects($this->once())
+            ->method('getShouldRedirectToCart')
+            ->willReturn(false);
+
+        $this->redirectMock->expects($this->once())
+            ->method('getRefererUrl')
+            ->willReturn($refererUrl);
+
+        $this->helperMock->expects($this->once())
+            ->method('calculate')
+            ->willReturnSelf();
+
+        $this->responseMock->expects($this->once())
+            ->method('setRedirect')
+            ->with($refererUrl)
+            ->willReturn($this->responseMock);
+
+        $this->assertEquals($this->responseMock, $this->model->execute());
+    }
+
+    public function testExecuteWithoutQuantityArrayAndOutOfStock()
+    {
+        $itemId = 2;
+        $wishlistId = 1;
+        $qty = [];
+        $productId = 4;
+        $indexUrl = 'index_url';
+        $configureUrl = 'configure_url';
+        $options = [5 => 'option'];
+        $params = ['item' => $itemId, 'qty' => $qty];
+
+        $itemMock = $this->getMockBuilder('Magento\Wishlist\Model\Item')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'load',
+                    'getId',
+                    'getWishlistId',
+                    'setQty',
+                    'setOptions',
+                    'getBuyRequest',
+                    'mergeBuyRequest',
+                    'addToCart',
+                    'getProduct',
+                    'getProductId',
+                ]
+            )
+            ->getMock();
+
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->exactly(2))
+            ->method('getId')
+            ->willReturn($itemId);
+        $itemMock->expects($this->once())
+            ->method('getWishlistId')
+            ->willReturn($wishlistId);
+
+        $wishlistMock = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->wishlistProviderMock->expects($this->once())
+            ->method('getWishlist')
+            ->with($wishlistId)
+            ->willReturn($wishlistMock);
+
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('qty', null)
+            ->willReturn($qty);
+
+        $this->quantityProcessorMock->expects($this->once())
+            ->method('process')
+            ->with(1)
+            ->willReturnArgument(0);
+
+        $itemMock->expects($this->once())
+            ->method('setQty')
+            ->with(1)
+            ->willReturnSelf();
+
+        $this->urlMock->expects($this->at(0))
+            ->method('getUrl')
+            ->with('*/*', null)
+            ->willReturn($indexUrl);
+
+        $itemMock->expects($this->once())
+            ->method('getProductId')
+            ->willReturn($productId);
+
+        $this->urlMock->expects($this->at(1))
+            ->method('getUrl')
+            ->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId])
+            ->willReturn($configureUrl);
+
+        $optionMock = $this->getMockBuilder('Magento\Wishlist\Model\Item\Option')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($optionMock);
+
+        $optionsMock = $this->getMockBuilder('Magento\Wishlist\Model\Resource\Item\Option\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $optionMock->expects($this->once())
+            ->method('getCollection')
+            ->willReturn($optionsMock);
+
+        $optionsMock->expects($this->once())
+            ->method('addItemFilter')
+            ->with([$itemId])
+            ->willReturnSelf();
+        $optionsMock->expects($this->once())
+            ->method('getOptionsByItem')
+            ->with($itemId)
+            ->willReturn($options);
+
+        $itemMock->expects($this->once())
+            ->method('setOptions')
+            ->with($options)
+            ->willReturnSelf();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParams')
+            ->willReturn($params);
+
+        $buyRequestMock = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $itemMock->expects($this->once())
+            ->method('getBuyRequest')
+            ->willReturn($buyRequestMock);
+
+        $this->productHelperMock->expects($this->once())
+            ->method('addParamsToBuyRequest')
+            ->with($params, ['current_config' => $buyRequestMock])
+            ->willReturn($buyRequestMock);
+
+        $itemMock->expects($this->once())
+            ->method('mergeBuyRequest')
+            ->with($buyRequestMock)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('addToCart')
+            ->with($this->checkoutCartMock, true)
+            ->willThrowException(
+                new \Magento\Framework\Model\Exception(null, \Magento\Wishlist\Model\Item::EXCEPTION_CODE_NOT_SALABLE)
+            );
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addError')
+            ->with('This product(s) is out of stock.', null)
+            ->willReturnSelf();
+
+        $this->helperMock->expects($this->once())
+            ->method('calculate')
+            ->willReturnSelf();
+
+        $this->responseMock->expects($this->once())
+            ->method('setRedirect')
+            ->with($indexUrl)
+            ->willReturn($this->responseMock);
+
+        $this->assertEquals($this->responseMock, $this->model->execute());
+    }
+
+    public function testExecuteWithoutQuantityArrayAndConfigurable()
+    {
+        $itemId = 2;
+        $wishlistId = 1;
+        $qty = [];
+        $productId = 4;
+        $indexUrl = 'index_url';
+        $configureUrl = 'configure_url';
+        $options = [5 => 'option'];
+        $params = ['item' => $itemId, 'qty' => $qty];
+
+        $itemMock = $this->getMockBuilder('Magento\Wishlist\Model\Item')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'load',
+                    'getId',
+                    'getWishlistId',
+                    'setQty',
+                    'setOptions',
+                    'getBuyRequest',
+                    'mergeBuyRequest',
+                    'addToCart',
+                    'getProduct',
+                    'getProductId',
+                ]
+            )
+            ->getMock();
+
+        $this->requestMock->expects($this->at(0))
+            ->method('getParam')
+            ->with('item', null)
+            ->willReturn($itemId);
+        $this->itemFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($itemMock);
+
+        $itemMock->expects($this->once())
+            ->method('load')
+            ->with($itemId, null)
+            ->willReturnSelf();
+        $itemMock->expects($this->exactly(2))
+            ->method('getId')
+            ->willReturn($itemId);
+        $itemMock->expects($this->once())
+            ->method('getWishlistId')
+            ->willReturn($wishlistId);
+
+        $wishlistMock = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->wishlistProviderMock->expects($this->once())
+            ->method('getWishlist')
+            ->with($wishlistId)
+            ->willReturn($wishlistMock);
+
+        $this->requestMock->expects($this->at(1))
+            ->method('getParam')
+            ->with('qty', null)
+            ->willReturn($qty);
+
+        $this->quantityProcessorMock->expects($this->once())
+            ->method('process')
+            ->with(1)
+            ->willReturnArgument(0);
+
+        $itemMock->expects($this->once())
+            ->method('setQty')
+            ->with(1)
+            ->willReturnSelf();
+
+        $this->urlMock->expects($this->at(0))
+            ->method('getUrl')
+            ->with('*/*', null)
+            ->willReturn($indexUrl);
+
+        $itemMock->expects($this->once())
+            ->method('getProductId')
+            ->willReturn($productId);
+
+        $this->urlMock->expects($this->at(1))
+            ->method('getUrl')
+            ->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId])
+            ->willReturn($configureUrl);
+
+        $optionMock = $this->getMockBuilder('Magento\Wishlist\Model\Item\Option')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->optionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($optionMock);
+
+        $optionsMock = $this->getMockBuilder('Magento\Wishlist\Model\Resource\Item\Option\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $optionMock->expects($this->once())
+            ->method('getCollection')
+            ->willReturn($optionsMock);
+
+        $optionsMock->expects($this->once())
+            ->method('addItemFilter')
+            ->with([$itemId])
+            ->willReturnSelf();
+        $optionsMock->expects($this->once())
+            ->method('getOptionsByItem')
+            ->with($itemId)
+            ->willReturn($options);
+
+        $itemMock->expects($this->once())
+            ->method('setOptions')
+            ->with($options)
+            ->willReturnSelf();
+
+        $this->requestMock->expects($this->once())
+            ->method('getParams')
+            ->willReturn($params);
+
+        $buyRequestMock = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $itemMock->expects($this->once())
+            ->method('getBuyRequest')
+            ->willReturn($buyRequestMock);
+
+        $this->productHelperMock->expects($this->once())
+            ->method('addParamsToBuyRequest')
+            ->with($params, ['current_config' => $buyRequestMock])
+            ->willReturn($buyRequestMock);
+
+        $itemMock->expects($this->once())
+            ->method('mergeBuyRequest')
+            ->with($buyRequestMock)
+            ->willReturnSelf();
+        $itemMock->expects($this->once())
+            ->method('addToCart')
+            ->with($this->checkoutCartMock, true)
+            ->willThrowException(
+                new \Magento\Framework\Model\Exception(
+                    'message',
+                    \Magento\Wishlist\Model\Item::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS
+                )
+            );
+
+        $this->messageManagerMock->expects($this->once())
+            ->method('addNotice')
+            ->with('message', null)
+            ->willReturnSelf();
+
+        $this->helperMock->expects($this->once())
+            ->method('calculate')
+            ->willReturnSelf();
+
+        $this->responseMock->expects($this->once())
+            ->method('setRedirect')
+            ->with($configureUrl)
+            ->willReturn($this->responseMock);
+
+        $this->assertEquals($this->responseMock, $this->model->execute());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Wishlist/Controller/WishlistProviderTest.php b/dev/tests/unit/testsuite/Magento/Wishlist/Controller/WishlistProviderTest.php
index c90f955d1c4adf994ea925b86979d014f4e897e9..5899fd32805bb3ceb08a1269587d7b0bb8acde1b 100644
--- a/dev/tests/unit/testsuite/Magento/Wishlist/Controller/WishlistProviderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Wishlist/Controller/WishlistProviderTest.php
@@ -73,7 +73,7 @@ class WishlistProviderTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->wishlistProvider = $objectManager->getObject(
-            '\Magento\Wishlist\Controller\WishlistProvider',
+            'Magento\Wishlist\Controller\WishlistProvider',
             [
                 'request' => $this->request,
                 'wishlistFactory' => $this->wishlistFactory,
diff --git a/dev/tools/Magento/Tools/Di/compiler.php b/dev/tools/Magento/Tools/Di/compiler.php
index f838a21987b9a7f1123b3d881765136e05b35ae5..6f185bc3587e6f03ddd65d6b934db10c5679f110 100644
--- a/dev/tools/Magento/Tools/Di/compiler.php
+++ b/dev/tools/Magento/Tools/Di/compiler.php
@@ -27,7 +27,7 @@ $codeScanDir = realpath($rootDir . '/app');
 try {
     $opt = new Zend_Console_Getopt(
         [
-            'serializer=w'         => 'serializer function that should be used (serialize|binary) default = serialize',
+            'serializer=w'         => 'serializer function that should be used (serialize|igbinary) default: serialize',
             'verbose|v'            => 'output report after tool run',
             'extra-classes-file=s' => 'path to file with extra proxies and factories to generate',
             'generation=s'         => 'absolute path to generated classes, <magento_root>/var/generation by default',
@@ -55,7 +55,7 @@ try {
     $errorWriter = new Writer\Console();
 
     $log = new Log($logWriter, $errorWriter);
-    $serializer = $opt->getOption('serializer') == 'binary' ? new Serializer\Igbinary() : new Serializer\Standard();
+    $serializer = $opt->getOption('serializer') == 'igbinary' ? new Serializer\Igbinary() : new Serializer\Standard();
 
     $validator = new \Magento\Framework\Code\Validator();
     $validator->add(new \Magento\Framework\Code\Validator\ConstructorIntegrity());
diff --git a/dev/tools/Magento/Tools/Migration/aliases_map/composite_modules_ce.php b/dev/tools/Magento/Tools/Migration/aliases_map/composite_modules_ce.php
index 4ca5ea24754a9243bdbaa27e1a49ba5366396bce..87a7483bde923a3e87bd5f0479a927652d090489 100644
--- a/dev/tools/Magento/Tools/Migration/aliases_map/composite_modules_ce.php
+++ b/dev/tools/Magento/Tools/Migration/aliases_map/composite_modules_ce.php
@@ -18,4 +18,4 @@ require_once realpath(
 ) . '/app/code/Magento/Core/Model/Resource/Setup/Migration.php';
 
 $objectManager = new \Magento\Framework\App\ObjectManager();
-return $objectManager->create('\Magento\Framework\Module\Setup\Migration')->getCompositeModules();
+return $objectManager->create('Magento\Framework\Module\Setup\Migration')->getCompositeModules();
diff --git a/dev/tools/performance-toolkit/fixtures/cart_price_rules.php b/dev/tools/performance-toolkit/fixtures/cart_price_rules.php
index 66cd24c33ad5c354687e2c56e03164569748573d..64fe5341887dc938a113bb97599993facfac0083 100644
--- a/dev/tools/performance-toolkit/fixtures/cart_price_rules.php
+++ b/dev/tools/performance-toolkit/fixtures/cart_price_rules.php
@@ -8,7 +8,7 @@ $cartPriceRulesProductsFloor = \Magento\ToolkitFramework\Config::getInstance()->
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->get('Magento\Catalog\Model\Category');
 /** @var $model  \Magento\SalesRule\Model\Rule*/
diff --git a/dev/tools/performance-toolkit/fixtures/catalog_price_rules.php b/dev/tools/performance-toolkit/fixtures/catalog_price_rules.php
index 626946cef99646c5dbe67f66b8424a7e7f0a1528..ab5c33e6a078431506f81a74f74fb7edbbcdf4bc 100644
--- a/dev/tools/performance-toolkit/fixtures/catalog_price_rules.php
+++ b/dev/tools/performance-toolkit/fixtures/catalog_price_rules.php
@@ -7,7 +7,7 @@ $catalogPriceRulesCount = \Magento\ToolkitFramework\Config::getInstance()->getVa
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->get('Magento\Catalog\Model\Category');
 /** @var $model  \Magento\CatalogRule\Model\Rule*/
diff --git a/dev/tools/performance-toolkit/fixtures/categories.php b/dev/tools/performance-toolkit/fixtures/categories.php
index f25a56829e44833bc8ccc8eed53a4261711b8578..c01e7090464c03d4df13f9696e148bcb58e55b33 100644
--- a/dev/tools/performance-toolkit/fixtures/categories.php
+++ b/dev/tools/performance-toolkit/fixtures/categories.php
@@ -8,7 +8,7 @@ $maxNestingLevel = \Magento\ToolkitFramework\Config::getInstance()->getValue('ca
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->create('Magento\Catalog\Model\Category');
 
diff --git a/dev/tools/performance-toolkit/fixtures/configurable_products.php b/dev/tools/performance-toolkit/fixtures/configurable_products.php
index 657a94b58694bd95adac0344270df4fb3ee711fb..49a2f6574bd87217aeebe870e04a5fea180c6b3e 100644
--- a/dev/tools/performance-toolkit/fixtures/configurable_products.php
+++ b/dev/tools/performance-toolkit/fixtures/configurable_products.php
@@ -7,7 +7,7 @@ $configurablesCount = \Magento\ToolkitFramework\Config::getInstance()->getValue(
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->get('Magento\Catalog\Model\Category');
 
diff --git a/dev/tools/performance-toolkit/fixtures/customers.php b/dev/tools/performance-toolkit/fixtures/customers.php
index 195e7ff6b00d7b6c9b28d52d033d78d38dfda7ac..0932c543886d025a8c71e1a7fdc74c512a23f83b 100644
--- a/dev/tools/performance-toolkit/fixtures/customers.php
+++ b/dev/tools/performance-toolkit/fixtures/customers.php
@@ -7,7 +7,7 @@ $customersNumber = \Magento\ToolkitFramework\Config::getInstance()->getValue('cu
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->get('Magento\Catalog\Model\Category');
 /** @var $defaultStoreView \Magento\Store\Model\Store */
diff --git a/dev/tools/performance-toolkit/fixtures/eav_variations.php b/dev/tools/performance-toolkit/fixtures/eav_variations.php
index e3f307a2ec678ed8988aae3a18823b2309f84b05..76e30a453a832d27e4579bf6024f33694a49e2e0 100644
--- a/dev/tools/performance-toolkit/fixtures/eav_variations.php
+++ b/dev/tools/performance-toolkit/fixtures/eav_variations.php
@@ -11,7 +11,7 @@ $model = $this->getObjectManager()->create('Magento\Catalog\Model\Resource\Eav\A
 /* @var $helper \Magento\Catalog\Helper\Product */
 $helper = $this->getObjectManager()->get('Magento\Catalog\Helper\Product');
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 $stores = $storeManager->getStores();
 $storeViewsCount = count($stores);
 
diff --git a/dev/tools/performance-toolkit/fixtures/simple_products.php b/dev/tools/performance-toolkit/fixtures/simple_products.php
index 755623b780ccb3f8490fe49f1e186e21bffc0790..ea54c518c1c5dbce9c3cddb6141f28f38f728130 100644
--- a/dev/tools/performance-toolkit/fixtures/simple_products.php
+++ b/dev/tools/performance-toolkit/fixtures/simple_products.php
@@ -7,7 +7,7 @@ $simpleProductsCount = \Magento\ToolkitFramework\Config::getInstance()->getValue
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->get('Magento\Catalog\Model\Category');
 
diff --git a/dev/tools/performance-toolkit/fixtures/stores.php b/dev/tools/performance-toolkit/fixtures/stores.php
index c2b932c846b5ac517ad06d07da89208f8247f02f..d58463ac2d9ad39169fb9960cee384bee0577d09 100644
--- a/dev/tools/performance-toolkit/fixtures/stores.php
+++ b/dev/tools/performance-toolkit/fixtures/stores.php
@@ -9,7 +9,7 @@ $storesCount = \Magento\ToolkitFramework\Config::getInstance()->getValue('store_
 $this->resetObjectManager();
 
 /** @var \Magento\Store\Model\StoreManager $storeManager */
-$storeManager = $this->getObjectManager()->create('\Magento\Store\Model\StoreManager');
+$storeManager = $this->getObjectManager()->create('Magento\Store\Model\StoreManager');
 /** @var $category \Magento\Catalog\Model\Category */
 $category = $this->getObjectManager()->create('Magento\Catalog\Model\Category');
 
diff --git a/lib/internal/Magento/Framework/App/Area.php b/lib/internal/Magento/Framework/App/Area.php
index f37822b1b231b8b43e3b6c3b67b683f886df8c2d..0cef58d915916088422c2cd04a7fa4c526f70f7c 100644
--- a/lib/internal/Magento/Framework/App/Area.php
+++ b/lib/internal/Magento/Framework/App/Area.php
@@ -62,7 +62,7 @@ class Area implements \Magento\Framework\App\AreaInterface
     protected $_diConfigLoader;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -84,7 +84,7 @@ class Area implements \Magento\Framework\App\AreaInterface
     protected $_designExceptions;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\TranslateInterface $translator
      * @param \Magento\Framework\ObjectManagerInterface $objectManager
@@ -95,7 +95,7 @@ class Area implements \Magento\Framework\App\AreaInterface
      * @param string $areaCode
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\TranslateInterface $translator,
         \Magento\Framework\ObjectManagerInterface $objectManager,
@@ -167,7 +167,7 @@ class Area implements \Magento\Framework\App\AreaInterface
                 return true;
             }
         } catch (\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
         }
         return false;
     }
diff --git a/lib/internal/Magento/Framework/App/Bootstrap.php b/lib/internal/Magento/Framework/App/Bootstrap.php
index e271ecb31206e4263528b7954b736cd258f34bff..c3808f5764af646b696c0ab44c3c81abe2b86c7a 100644
--- a/lib/internal/Magento/Framework/App/Bootstrap.php
+++ b/lib/internal/Magento/Framework/App/Bootstrap.php
@@ -410,7 +410,7 @@ class Bootstrap
                 if (!$this->objectManager) {
                     throw new \DomainException();
                 }
-                $this->objectManager->get('Magento\Framework\Logger')->logException($e);
+                $this->objectManager->get('Psr\Log\LoggerInterface')->critical($e);
             } catch (\Exception $e) {
                 $message .= "Could not write error message to log. Please use developer mode to see the message.\n";
             }
diff --git a/lib/internal/Magento/Framework/App/Helper/AbstractHelper.php b/lib/internal/Magento/Framework/App/Helper/AbstractHelper.php
index 9eace9044d1676d5a9b14d68f41a3da3389a57ee..175cb85b531febfdb61082798d867d66b7b59fe5 100644
--- a/lib/internal/Magento/Framework/App/Helper/AbstractHelper.php
+++ b/lib/internal/Magento/Framework/App/Helper/AbstractHelper.php
@@ -36,7 +36,7 @@ abstract class AbstractHelper
     protected $_moduleManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
diff --git a/lib/internal/Magento/Framework/App/Helper/Context.php b/lib/internal/Magento/Framework/App/Helper/Context.php
index 48cebe198961b820ed0c7b8f13fdc5f94e33a058..49ae5dd5be2c802952fa1aaf1dee646ffeef7804 100644
--- a/lib/internal/Magento/Framework/App/Helper/Context.php
+++ b/lib/internal/Magento/Framework/App/Helper/Context.php
@@ -24,7 +24,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     protected $_eventManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -66,7 +66,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     /**
      * @param \Magento\Framework\Url\EncoderInterface $urlEncoder
      * @param \Magento\Framework\Url\DecoderInterface $urlDecoder
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Translate\InlineInterface $translateInline
      * @param \Magento\Framework\Module\Manager $moduleManager
      * @param \Magento\Framework\App\RequestInterface $httpRequest
@@ -81,7 +81,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     public function __construct(
         \Magento\Framework\Url\EncoderInterface $urlEncoder,
         \Magento\Framework\Url\DecoderInterface $urlDecoder,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Translate\InlineInterface $translateInline,
         \Magento\Framework\Module\Manager $moduleManager,
         \Magento\Framework\App\RequestInterface $httpRequest,
@@ -153,7 +153,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     }
 
     /**
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php
index 2e3f2de0cc7d8da31bbfff3243bc6a0a0db7289d..d5128f358d6ef2dd38a91fded6e68325f87ce607 100644
--- a/lib/internal/Magento/Framework/AppInterface.php
+++ b/lib/internal/Magento/Framework/AppInterface.php
@@ -16,7 +16,7 @@ interface AppInterface
     /**
      * Magento version
      */
-    const VERSION = '0.42.0-beta1';
+    const VERSION = '0.42.0-beta2';
 
     /**
      * Launch application
diff --git a/lib/internal/Magento/Framework/DB/AbstractMapper.php b/lib/internal/Magento/Framework/DB/AbstractMapper.php
index d6cac55a45e27193fa0cf6c73e10b77155576c14..cde379716e23fdeb612e1decac3abfd93b76312e 100644
--- a/lib/internal/Magento/Framework/DB/AbstractMapper.php
+++ b/lib/internal/Magento/Framework/DB/AbstractMapper.php
@@ -8,7 +8,7 @@ use Magento\Framework\Api\CriteriaInterface;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 use Magento\Framework\Data\ObjectFactory;
 use Magento\Framework\DB\Adapter\AdapterInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Object;
 
 /**
diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
index 6f5b30cc40c7d96a5059ce095cff06bac983b2f7..b63ca6b8f22ee55bd15b87f1e63afd1033f124dd 100644
--- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
+++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
@@ -444,7 +444,7 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
 
                 if (!$retry) {
                     $this->logger->logStats(LoggerInterface::TYPE_QUERY, $sql, $bind);
-                    $this->logger->logException($e);
+                    $this->logger->critical($e);
                     throw $e;
                 }
             }
diff --git a/lib/internal/Magento/Framework/DB/Logger/File.php b/lib/internal/Magento/Framework/DB/Logger/File.php
index 70ac5f4064a0a5f0a37c5b604b0f7054a2900d0c..f658077b3768543e68efffed9d2d512c7690d9d1 100644
--- a/lib/internal/Magento/Framework/DB/Logger/File.php
+++ b/lib/internal/Magento/Framework/DB/Logger/File.php
@@ -72,7 +72,7 @@ class File extends LoggerAbstract
     /**
      * {@inheritdoc}
      */
-    public function logException(\Exception $e)
+    public function critical(\Exception $e)
     {
         $this->log("EXCEPTION \n$e\n\n");
     }
diff --git a/lib/internal/Magento/Framework/DB/Logger/Null.php b/lib/internal/Magento/Framework/DB/Logger/Null.php
index 7b7dfbb1a791d1d32f35f8018e0cf458ae25ce22..8aafe5118ca3cecdfd7051ce6fa2aa79a5da6aaa 100644
--- a/lib/internal/Magento/Framework/DB/Logger/Null.php
+++ b/lib/internal/Magento/Framework/DB/Logger/Null.php
@@ -23,7 +23,7 @@ class Null implements \Magento\Framework\DB\LoggerInterface
     /**
      * {@inheritdoc}
      */
-    public function logException(\Exception $e)
+    public function critical(\Exception $e)
     {
     }
 
diff --git a/lib/internal/Magento/Framework/DB/LoggerInterface.php b/lib/internal/Magento/Framework/DB/LoggerInterface.php
index e937704ac26f61fde5634d68993a6b185c83e8fa..28b39bc1342241ef3cd24fb5cf7223061a69ce10 100644
--- a/lib/internal/Magento/Framework/DB/LoggerInterface.php
+++ b/lib/internal/Magento/Framework/DB/LoggerInterface.php
@@ -43,5 +43,5 @@ interface LoggerInterface
      * @param \Exception $e
      * @return void
      */
-    public function logException(\Exception $e);
+    public function critical(\Exception $e);
 }
diff --git a/lib/internal/Magento/Framework/DB/Query.php b/lib/internal/Magento/Framework/DB/Query.php
index 39ef80941e14d0171d45eb1b410ce3e3bbee6d38..15e6575326c2ad8e51de4fb2f47f12dc598b222f 100644
--- a/lib/internal/Magento/Framework/DB/Query.php
+++ b/lib/internal/Magento/Framework/DB/Query.php
@@ -4,7 +4,7 @@
  */
 namespace Magento\Framework\DB;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Class Query
diff --git a/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php b/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php
index c7571d72e895783158b1d88ce2368881bc3968f7..6845e5edd8fd41bf02eca6291742b06288d4ff86 100644
--- a/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php
+++ b/lib/internal/Magento/Framework/Data/AbstractSearchCriteriaBuilder.php
@@ -4,7 +4,7 @@
  */
 namespace Magento\Framework\Data;
 
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Class AbstractSearchCriteriaBuilder
diff --git a/lib/internal/Magento/Framework/Data/Collection/Db.php b/lib/internal/Magento/Framework/Data/Collection/Db.php
index 2d756703476d974731f6c182602a83aac55c728a..a3d0b641186d68a815f88646344fa40e87a14224 100644
--- a/lib/internal/Magento/Framework/Data/Collection/Db.php
+++ b/lib/internal/Magento/Framework/Data/Collection/Db.php
@@ -7,7 +7,7 @@ namespace Magento\Framework\Data\Collection;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\DB\Select;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Base items collection class
@@ -709,7 +709,7 @@ class Db extends \Magento\Framework\Data\Collection
      */
     protected function _logQuery($sql)
     {
-        $this->_logger->log(is_null($sql) ? $this->getSelect()->__toString() : $sql);
+        $this->_logger->info(is_null($sql) ? $this->getSelect()->__toString() : $sql);
     }
 
     /**
diff --git a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php
index 8a2222a26956cbeaa0e3d2727030e5a2bc482147..bd5b3a6cf23752f9592caea020013eebec9a5d71 100644
--- a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php
+++ b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php
@@ -153,7 +153,7 @@ abstract class AbstractAdapter implements AdapterInterface
     protected $directoryWrite;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -675,8 +675,7 @@ abstract class AbstractAdapter implements AdapterInterface
             try {
                 $this->directoryWrite->create($this->directoryWrite->getRelativePath($destination));
             } catch (\Magento\Framework\Filesystem\FilesystemException $e) {
-                $this->logger->addStreamLog(\Magento\Framework\Logger::LOGGER_SYSTEM);
-                $this->logger->log($e->getMessage());
+                $this->logger->critical($e);
                 throw new \Exception('Unable to write file into directory ' . $destination . '. Access forbidden.');
             }
         }
diff --git a/lib/internal/Magento/Framework/Less/PreProcessor/ErrorHandler.php b/lib/internal/Magento/Framework/Less/PreProcessor/ErrorHandler.php
index 58332f1ef3df91ad8a1526af58e726f401a5a31c..331ce1d74e15dff542785604f72c8cfd8c1e9a02 100644
--- a/lib/internal/Magento/Framework/Less/PreProcessor/ErrorHandler.php
+++ b/lib/internal/Magento/Framework/Less/PreProcessor/ErrorHandler.php
@@ -10,14 +10,14 @@ namespace Magento\Framework\Less\PreProcessor;
 class ErrorHandler implements ErrorHandlerInterface
 {
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
-    public function __construct(\Magento\Framework\Logger $logger)
+    public function __construct(\Psr\Log\LoggerInterface $logger)
     {
         $this->logger = $logger;
     }
@@ -27,6 +27,6 @@ class ErrorHandler implements ErrorHandlerInterface
      */
     public function processException(\Exception $e)
     {
-        $this->logger->logException($e);
+        $this->logger->critical($e);
     }
 }
diff --git a/lib/internal/Magento/Framework/Logger.php b/lib/internal/Magento/Framework/Logger.php
deleted file mode 100644
index 378f2099dc4b79f85dae3359bd499162fd15cedc..0000000000000000000000000000000000000000
--- a/lib/internal/Magento/Framework/Logger.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-namespace Magento\Framework;
-
-use Magento\Framework\App\Filesystem\DirectoryList;
-
-/**
- * Logger model
- */
-class Logger
-{
-    /**#@+
-     * Keys that stand for particular log streams
-     */
-    const LOGGER_SYSTEM = 'system';
-
-    const LOGGER_EXCEPTION = 'exception';
-
-    /**#@-*/
-
-    /**
-     * @var array
-     */
-    protected $_loggers = [];
-
-    /**
-     * @var \Magento\Framework\Filesystem
-     */
-    protected $_filesystem;
-
-    /**
-     * @param \Magento\Framework\Filesystem $filesystem
-     * @param string $defaultFile
-     */
-    public function __construct(\Magento\Framework\Filesystem $filesystem, $defaultFile = '')
-    {
-        $this->_filesystem = $filesystem;
-        $this->addStreamLog(self::LOGGER_SYSTEM, $defaultFile)->addStreamLog(self::LOGGER_EXCEPTION, $defaultFile);
-    }
-
-    /**
-     * Add a logger by specified key
-     *
-     * Second argument is a file name (relative to log directory) or a PHP "wrapper"
-     *
-     * @param string $loggerKey
-     * @param string $fileOrWrapper
-     * @param string $writerClass
-     * @return \Magento\Framework\Logger
-     * @link http://php.net/wrappers
-     */
-    public function addStreamLog($loggerKey, $fileOrWrapper = '', $writerClass = '')
-    {
-        $file = $fileOrWrapper ?: "{$loggerKey}.log";
-        if (!preg_match('#^[a-z][a-z0-9+.-]*\://#i', $file)) {
-            $logDir = $this->_filesystem->getDirectoryWrite(DirectoryList::LOG);
-            $logDir->create();
-            $file = $logDir->getAbsolutePath($file);
-        }
-        if (!$writerClass || !is_subclass_of($writerClass, 'Zend_Log_Writer_Stream')) {
-            $writerClass = 'Zend_Log_Writer_Stream';
-        }
-        /** @var $writer \Zend_Log_Writer_Stream */
-        $writer = $writerClass::factory(['stream' => $file]);
-        $writer->setFormatter(
-            new \Zend_Log_Formatter_Simple('%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL)
-        );
-        $this->_loggers[$loggerKey] = new \Zend_Log($writer);
-        return $this;
-    }
-
-    /**
-     * Unset all declared loggers
-     *
-     * @return $this
-     */
-    public function unsetLoggers()
-    {
-        $this->_loggers = [];
-        return $this;
-    }
-
-    /**
-     * Check whether a logger exists by specified key
-     *
-     * @param string $key
-     * @return bool
-     */
-    public function hasLog($key)
-    {
-        return isset($this->_loggers[$key]);
-    }
-
-    /**
-     * Log a message
-     *
-     * @param string $message
-     * @param int $level
-     * @param string $loggerKey
-     * @return void
-     */
-    public function log($message, $level = \Zend_Log::DEBUG, $loggerKey = self::LOGGER_SYSTEM)
-    {
-        if (!isset($this->_loggers[$loggerKey])) {
-            return;
-        }
-        if (is_array($message) || is_object($message)) {
-            $message = print_r($message, true);
-        }
-        /** @var $logger \Zend_Log */
-        $logger = $this->_loggers[$loggerKey];
-        $logger->log($message, $level);
-    }
-
-    /**
-     * Log a message in specific file
-     *
-     * @param string $message
-     * @param int $level
-     * @param string $file
-     * @return void
-     */
-    public function logFile($message, $level = \Zend_Log::DEBUG, $file = '')
-    {
-        if (!isset($file)) {
-            $this->log($message, $level);
-        }
-        if (is_array($message) || is_object($message)) {
-            $message = print_r($message, true);
-        }
-        /** @var $logger \Zend_Log */
-        if (!$this->hasLog($file)) {
-            $this->addStreamLog($file, $file);
-        }
-        /** @var $logger \Zend_Log */
-        $this->log($message, $level, $file);
-    }
-
-    /**
-     * Log a message with "debug" level
-     *
-     * @param string $message
-     * @param string $loggerKey
-     * @return void
-     */
-    public function logDebug($message, $loggerKey = self::LOGGER_SYSTEM)
-    {
-        $this->log($message, \Zend_Log::DEBUG, $loggerKey);
-    }
-
-    /**
-     * Log an exception
-     *
-     * @param \Exception $e
-     * @return void
-     */
-    public function logException(\Exception $e)
-    {
-        $this->log("\n" . $e->__toString(), \Zend_Log::ERR, self::LOGGER_EXCEPTION);
-    }
-}
diff --git a/lib/internal/Magento/Framework/Logger/Adapter.php b/lib/internal/Magento/Framework/Logger/Adapter.php
deleted file mode 100644
index 404795cde9ba0c33479d4657baf912516682fa51..0000000000000000000000000000000000000000
--- a/lib/internal/Magento/Framework/Logger/Adapter.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- */
-namespace Magento\Framework\Logger;
-
-/**
- * Log Adapter
- */
-class Adapter
-{
-    /**
-     * Log file name
-     *
-     * @var string
-     */
-    protected $_logFileName = '';
-
-    /**
-     * Data to log
-     *
-     * @var array
-     */
-    protected $_data = [];
-
-    /**
-     * Fields that should be replaced in debug data with '***'
-     *
-     * @var array
-     */
-    protected $_debugReplacePrivateDataKeys = [];
-
-    /**
-     * @var \Magento\Framework\Logger
-     */
-    protected $_logger;
-
-    /**
-     * Set log file name
-     *
-     * @param \Magento\Framework\Logger $logger
-     * @param string $fileName
-     */
-    public function __construct(\Magento\Framework\Logger $logger, $fileName)
-    {
-        $this->_logFileName = $fileName;
-        $this->_logger = $logger;
-    }
-
-    /**
-     * Perform forced log data to file
-     *
-     * @param mixed $data
-     * @return $this
-     */
-    public function log($data = null)
-    {
-        if ($data === null) {
-            $data = $this->_data;
-        } else {
-            if (!is_array($data)) {
-                $data = [$data];
-            }
-        }
-        $data = $this->_filterDebugData($data);
-        $data['__pid'] = getmypid();
-        $this->_logger->logFile($data, \Zend_Log::DEBUG, $this->_logFileName);
-        return $this;
-    }
-
-    /**
-     * Log data setter
-     *
-     * @param string|array $key
-     * @param mixed $value
-     * @return $this
-     */
-    public function setData($key, $value = null)
-    {
-        if (is_array($key)) {
-            $this->_data = $key;
-        } else {
-            $this->_data[$key] = $value;
-        }
-        return $this;
-    }
-
-    /**
-     * Setter for private data keys, that should be replaced in debug data with '***'
-     *
-     * @param array $keys
-     * @return $this
-     */
-    public function setFilterDataKeys($keys)
-    {
-        if (!is_array($keys)) {
-            $keys = [$keys];
-        }
-        $this->_debugReplacePrivateDataKeys = $keys;
-        return $this;
-    }
-
-    /**
-     * Recursive filter data by private conventions
-     *
-     * @param mixed $debugData
-     * @return string|array
-     */
-    protected function _filterDebugData($debugData)
-    {
-        if (is_array($debugData) && is_array($this->_debugReplacePrivateDataKeys)) {
-            foreach ($debugData as $key => $value) {
-                if (in_array($key, $this->_debugReplacePrivateDataKeys)) {
-                    $debugData[$key] = '****';
-                } else {
-                    if (is_array($debugData[$key])) {
-                        $debugData[$key] = $this->_filterDebugData($debugData[$key]);
-                    }
-                }
-            }
-        }
-        return $debugData;
-    }
-}
diff --git a/lib/internal/Magento/Framework/Logger/Handler/Critical.php b/lib/internal/Magento/Framework/Logger/Handler/Critical.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f2a1950179d3481ca9b5dd178085c5ebe49fc1e
--- /dev/null
+++ b/lib/internal/Magento/Framework/Logger/Handler/Critical.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Framework\Logger\Handler;
+
+use Monolog\Logger;
+
+class Critical extends System
+{
+    /**
+     * @var string
+     */
+    protected $fileName = '/var/log/exception.log';
+
+    /**
+     * @var int
+     */
+    protected $loggerType = Logger::CRITICAL;
+}
diff --git a/lib/internal/Magento/Framework/Logger/Handler/Debug.php b/lib/internal/Magento/Framework/Logger/Handler/Debug.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed360efb95dd0d4c7aa1e68e1275b99c151e88bc
--- /dev/null
+++ b/lib/internal/Magento/Framework/Logger/Handler/Debug.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Framework\Logger\Handler;
+
+use Monolog\Logger;
+
+class Debug extends System
+{
+    /**
+     * @var string
+     */
+    protected $fileName = '/var/log/debug.log';
+
+    /**
+     * @var int
+     */
+    protected $loggerType = Logger::DEBUG;
+}
diff --git a/lib/internal/Magento/Framework/Logger/Handler/System.php b/lib/internal/Magento/Framework/Logger/Handler/System.php
new file mode 100644
index 0000000000000000000000000000000000000000..39f50b524d99b3dcecaa679b8ed18ca1959dd92e
--- /dev/null
+++ b/lib/internal/Magento/Framework/Logger/Handler/System.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Framework\Logger\Handler;
+
+use Magento\Framework\Filesystem\DriverInterface;
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+
+class System extends StreamHandler
+{
+    /**
+     * @var string
+     */
+    protected $fileName = '/var/log/system.log';
+
+    /**
+     * @var int
+     */
+    protected $loggerType = Logger::INFO;
+
+    /**
+     * @var DriverInterface
+     */
+    protected $filesystem;
+
+    /**
+     * @param DriverInterface $filesystem
+     */
+    public function __construct(DriverInterface $filesystem)
+    {
+        $this->filesystem = $filesystem;
+        parent::__construct(BP . $this->fileName, $this->loggerType);
+    }
+
+    /**
+     * @{inerhitDoc}
+     *
+     * @param $record array
+     * @return void
+     */
+    public function write(array $record)
+    {
+        $logDir = $this->filesystem->getParentDirectory($this->url);
+        if (!$this->filesystem->isDirectory($logDir)) {
+            $this->filesystem->createDirectory($logDir, 0777);
+        }
+        parent::write($record);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Logger/Monolog.php b/lib/internal/Magento/Framework/Logger/Monolog.php
new file mode 100644
index 0000000000000000000000000000000000000000..304528bf4c917e90f028517308a223ad2c2d2f90
--- /dev/null
+++ b/lib/internal/Magento/Framework/Logger/Monolog.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ */
+
+namespace Magento\Framework\Logger;
+
+use Monolog\Logger;
+
+class Monolog extends Logger
+{
+}
diff --git a/lib/internal/Magento/Framework/Logger/README.md b/lib/internal/Magento/Framework/Logger/README.md
index 09eb8ee4505ef1e520742128ba8b5603b76ec71d..2d2b0410de1d1fd392c3d5573453cd09494b7514 100644
--- a/lib/internal/Magento/Framework/Logger/README.md
+++ b/lib/internal/Magento/Framework/Logger/README.md
@@ -1,5 +1,3 @@
 # Logger
 
 **Logger** provides a standard mechanism to log to system and error logs.
-
-* **Adapter** will filter out debug information.
\ No newline at end of file
diff --git a/lib/internal/Magento/Framework/Message/Manager.php b/lib/internal/Magento/Framework/Message/Manager.php
index 01c7eee8f42a7171bece772718ad77c046fc15fd..739cdb0dbf5dc2a56e67e975416b70a42549c9eb 100644
--- a/lib/internal/Magento/Framework/Message/Manager.php
+++ b/lib/internal/Magento/Framework/Message/Manager.php
@@ -5,7 +5,7 @@
 namespace Magento\Framework\Message;
 
 use Magento\Framework\Event\ManagerInterface as EventManagerInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 
 /**
  * Message manager model
@@ -258,7 +258,7 @@ class Manager implements ManagerInterface
             $exception->getTraceAsString()
         );
 
-        $this->logger->logFile($message, \Zend_Log::DEBUG, Logger::LOGGER_EXCEPTION);
+        $this->logger->critical($message);
         $this->addMessage($this->messageFactory->create(MessageInterface::TYPE_ERROR, $alternativeText), $group);
         return $this;
     }
diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php
index 9bf7cd8b941291b962afa1560033852b37e45414..b223b53f1ce17fcbd49e594621441d18503be41d 100644
--- a/lib/internal/Magento/Framework/Model/AbstractModel.php
+++ b/lib/internal/Magento/Framework/Model/AbstractModel.php
@@ -109,7 +109,7 @@ abstract class AbstractModel extends \Magento\Framework\Object
     protected $_registry;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
diff --git a/lib/internal/Magento/Framework/Model/Context.php b/lib/internal/Magento/Framework/Model/Context.php
index 2b2835b5a20ed36a5126e5cd9263c82cdcb0516f..78f7125d2548710efc8ef2d82ac707af828e436e 100644
--- a/lib/internal/Magento/Framework/Model/Context.php
+++ b/lib/internal/Magento/Framework/Model/Context.php
@@ -19,7 +19,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     protected $_cacheManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -34,14 +34,14 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     protected $_actionValidator;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Event\ManagerInterface $eventDispatcher
      * @param \Magento\Framework\App\CacheInterface $cacheManager
      * @param \Magento\Framework\App\State $appState
      * @param \Magento\Framework\Model\ActionValidator\RemoveAction $actionValidator
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Event\ManagerInterface $eventDispatcher,
         \Magento\Framework\App\CacheInterface $cacheManager,
         \Magento\Framework\App\State $appState,
@@ -71,7 +71,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     }
 
     /**
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php
index aead4c8901f03fc6da9e432ec510812be6762f43..6e68ed3552d56043ae9e9abeb84cf10a5652f0e0 100644
--- a/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php
@@ -95,7 +95,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
 
     /**
      * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Zend_Db_Adapter_Abstract $connection
@@ -103,7 +103,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
      */
     public function __construct(
         \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         $connection = null,
diff --git a/lib/internal/Magento/Framework/Module/DataSetup.php b/lib/internal/Magento/Framework/Module/DataSetup.php
index 2e2a93ccc93cc19f512ad2dcf008c5c336fa49d3..7612e372fa0a7b7c6ecf06fdfd3d3e90a0479250 100644
--- a/lib/internal/Magento/Framework/Module/DataSetup.php
+++ b/lib/internal/Magento/Framework/Module/DataSetup.php
@@ -50,7 +50,7 @@ class DataSetup extends \Magento\Framework\Module\Setup implements \Magento\Fram
     protected $_eventManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -223,9 +223,9 @@ class DataSetup extends \Magento\Framework\Module\Setup implements \Magento\Fram
 
                 if ($result) {
                     $this->_resource->setDataVersion($this->_resourceName, $file['toVersion']);
-                    $this->_logger->log($fileName);
+                    $this->_logger->info($fileName);
                 } else {
-                    $this->_logger->log("Failed resource setup: {$fileName}");
+                    $this->_logger->info("Failed resource setup: {$fileName}");
                 }
             } catch (\Exception $e) {
                 throw new \Magento\Framework\Exception(
diff --git a/lib/internal/Magento/Framework/Module/Setup/Context.php b/lib/internal/Magento/Framework/Module/Setup/Context.php
index 5eb9006f3633c6599b375de5dc5d4199b71f3572..a2fcecf9f14f9e2988e522807088cba9c063983f 100644
--- a/lib/internal/Magento/Framework/Module/Setup/Context.php
+++ b/lib/internal/Magento/Framework/Module/Setup/Context.php
@@ -7,7 +7,7 @@ namespace Magento\Framework\Module\Setup;
 class Context implements \Magento\Framework\ObjectManager\ContextInterface
 {
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -54,7 +54,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     /**
      * Constructor
      *
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Framework\App\Resource $appResource
      * @param \Magento\Framework\Module\Dir\Reader $modulesReader
@@ -65,7 +65,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
      * @param \Magento\Framework\Filesystem $filesystem
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Event\ManagerInterface $eventManager,
         \Magento\Framework\App\Resource $appResource,
         \Magento\Framework\Module\Dir\Reader $modulesReader,
@@ -95,7 +95,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     }
 
     /**
-     * @return \Magento\Framework\Logger $logger
+     * @return \Psr\Log\LoggerInterface $logger
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php
index 901eded854db02ecca7352a62281b0c2f523de00..8756180f16b5b1a3250bb04b7acce6f496380d25 100644
--- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php
+++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php
@@ -157,7 +157,7 @@ class TypeProcessor
             }
             $reflection = new ClassReflection($class);
             $docBlock = $reflection->getDocBlock();
-            $this->_types[$typeName]['documentation'] = $docBlock ? $this->_getDescription($docBlock) : '';
+            $this->_types[$typeName]['documentation'] = $docBlock ? $this->getDescription($docBlock) : '';
             /** @var \Zend\Code\Reflection\MethodReflection $methodReflection */
             foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $methodReflection) {
                 if ($methodReflection->class === "Magento\Framework\Model\AbstractModel") {
@@ -200,7 +200,7 @@ class TypeProcessor
      * @param \Zend\Code\Reflection\DocBlockReflection $doc
      * @return string
      */
-    protected function _getDescription(\Zend\Code\Reflection\DocBlockReflection $doc)
+    public function getDescription(\Zend\Code\Reflection\DocBlockReflection $doc)
     {
         $shortDescription = $doc->getShortDescription();
         $longDescription = $doc->getLongDescription();
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/AggregationFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/AggregationFactory.php
index be11aaf87c0475008cdd5858154b1b2c1ce84e69..67737e0c191b48f5fb12ff8c4a6a95a8ad09540b 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/AggregationFactory.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/AggregationFactory.php
@@ -43,7 +43,7 @@ class AggregationFactory
                 ]
             );
         }
-        return $this->objectManager->create('\Magento\Framework\Search\Response\Aggregation', ['buckets' => $buckets]);
+        return $this->objectManager->create('Magento\Framework\Search\Response\Aggregation', ['buckets' => $buckets]);
     }
 
     /**
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/DocumentFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/DocumentFactory.php
index 5088c01d6e5e5eed0c6975b4988f9ca9e2168250..0f96fb6a5aacadc84c0ed34236ab3ff8cfd916c0 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/DocumentFactory.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/DocumentFactory.php
@@ -49,11 +49,11 @@ class DocumentFactory
             if ($rawField['name'] == $entityId) {
                 $documentId = $rawField['value'];
             } else {
-                $fields[] = $this->objectManager->create('\Magento\Framework\Search\DocumentField', $rawField);
+                $fields[] = $this->objectManager->create('Magento\Framework\Search\DocumentField', $rawField);
             }
         }
         return $this->objectManager->create(
-            '\Magento\Framework\Search\Document',
+            'Magento\Framework\Search\Document',
             ['documentFields' => $fields, 'documentId' => $documentId]
         );
     }
diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
index dcc8e1b08f4ade78722f2ed2429715f7caf1afd1..7a79ca11e61ca4ef2bcbe620492b78c2f409b9e6 100644
--- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
+++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ResponseFactory.php
@@ -62,7 +62,7 @@ class ResponseFactory
         /** @var \Magento\Framework\Search\Response\Aggregation $aggregations */
         $aggregations = $this->aggregationFactory->create($rawResponse['aggregations']);
         return $this->objectManager->create(
-            '\Magento\Framework\Search\Response\QueryResponse',
+            'Magento\Framework\Search\Response\QueryResponse',
             [
                 'documents' => $documents,
                 'aggregations' => $aggregations
diff --git a/lib/internal/Magento/Framework/View/Asset/Merged.php b/lib/internal/Magento/Framework/View/Asset/Merged.php
index c91500992fbc5b7f0fb8eb0d22994de5c381047e..9bb0d8f4097529ed2378f21819f9fe9199a22d86 100644
--- a/lib/internal/Magento/Framework/View/Asset/Merged.php
+++ b/lib/internal/Magento/Framework/View/Asset/Merged.php
@@ -10,7 +10,7 @@ namespace Magento\Framework\View\Asset;
 class Merged implements \Iterator
 {
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -40,14 +40,14 @@ class Merged implements \Iterator
     protected $isInitialized = false;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param MergeStrategyInterface $mergeStrategy
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param MergeableInterface[] $assets
      * @throws \InvalidArgumentException
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         MergeStrategyInterface $mergeStrategy,
         \Magento\Framework\View\Asset\Repository $assetRepo,
         array $assets
@@ -91,7 +91,7 @@ class Merged implements \Iterator
                 $this->mergeStrategy->merge($this->assets, $mergedAsset);
                 $this->assets = [$mergedAsset];
             } catch (\Exception $e) {
-                $this->logger->logException($e);
+                $this->logger->critical($e);
             }
         }
     }
diff --git a/lib/internal/Magento/Framework/View/Asset/Minified.php b/lib/internal/Magento/Framework/View/Asset/Minified.php
index adc98daa17d0491b4ffd815e891537a9c5238c64..17e5230e458bf1d82cb14d479dadde64d0e76c28 100644
--- a/lib/internal/Magento/Framework/View/Asset/Minified.php
+++ b/lib/internal/Magento/Framework/View/Asset/Minified.php
@@ -74,7 +74,7 @@ class Minified implements MergeableInterface
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -103,7 +103,7 @@ class Minified implements MergeableInterface
      * Constructor
      *
      * @param LocalInterface $asset
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Filesystem $filesystem
      * @param \Magento\Framework\UrlInterface $baseUrl
      * @param \Magento\Framework\Code\Minifier\AdapterInterface $adapter
@@ -111,7 +111,7 @@ class Minified implements MergeableInterface
      */
     public function __construct(
         LocalInterface $asset,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Filesystem $filesystem,
         \Magento\Framework\UrlInterface $baseUrl,
         \Magento\Framework\Code\Minifier\AdapterInterface $adapter,
@@ -223,7 +223,7 @@ class Minified implements MergeableInterface
             try {
                 $this->fillPropertiesByMinifyingAsset();
             } catch (\Exception $e) {
-                $this->logger->logException(
+                $this->logger->critical(
                     new \Magento\Framework\Exception(
                         'Could not minify file: ' . $this->originalAsset->getSourceFile(),
                         0,
diff --git a/lib/internal/Magento/Framework/View/Context.php b/lib/internal/Magento/Framework/View/Context.php
index 2c3f94525545241d8ae7dec25baf756e81c6b5f6..df294c469070e4d211133b52982a184ddf7a75c8 100644
--- a/lib/internal/Magento/Framework/View/Context.php
+++ b/lib/internal/Magento/Framework/View/Context.php
@@ -11,7 +11,7 @@ use Magento\Framework\App\FrontControllerInterface;
 use Magento\Framework\App\Request\Http as Request;
 use Magento\Framework\App\State as AppState;
 use Magento\Framework\Event\ManagerInterface;
-use Magento\Framework\Logger;
+use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Session\SessionManager;
 use Magento\Framework\TranslateInterface;
 use Magento\Framework\UrlInterface;
@@ -114,7 +114,7 @@ class Context
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -302,7 +302,7 @@ class Context
     /**
      * Retrieve logger
      *
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/View/Design/Theme/Image.php b/lib/internal/Magento/Framework/View/Design/Theme/Image.php
index 1c4f224706f94a426713f7f3e0df71d904ac3bff..5408f611b83a22f7d9ec99875744572c99036ccb 100644
--- a/lib/internal/Magento/Framework/View/Design/Theme/Image.php
+++ b/lib/internal/Magento/Framework/View/Design/Theme/Image.php
@@ -63,7 +63,7 @@ class Image
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -88,7 +88,7 @@ class Image
      * @param \Magento\Framework\Image\Factory $imageFactory
      * @param Image\Uploader $uploader
      * @param Image\PathInterface $themeImagePath
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param array $imageParams
      * @param ThemeInterface $theme
      * @codingStandardsIgnoreStart
@@ -98,7 +98,7 @@ class Image
         \Magento\Framework\Image\Factory $imageFactory,
         Image\Uploader $uploader,
         Image\PathInterface $themeImagePath,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         array $imageParams = [self::PREVIEW_IMAGE_WIDTH, self::PREVIEW_IMAGE_HEIGHT],
         ThemeInterface $theme = null
     ) {
@@ -158,7 +158,7 @@ class Image
             $this->theme->setPreviewImage($destinationFileName);
         } catch (\Magento\Framework\Filesystem\FilesystemException $e) {
             $this->theme->setPreviewImage(null);
-            $this->logger->logException($e);
+            $this->logger->critical($e);
         }
         return $isCopied;
     }
diff --git a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
index c270bbd52af27a35901dc817c8de4109580adaba..56689fe7335ae1bf90a8feddc1e35826ab935864 100644
--- a/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
+++ b/lib/internal/Magento/Framework/View/Element/AbstractBlock.php
@@ -117,7 +117,7 @@ abstract class AbstractBlock extends \Magento\Framework\Object implements BlockI
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -743,7 +743,7 @@ abstract class AbstractBlock extends \Magento\Framework\Object implements BlockI
             $params = array_merge(['_secure' => $this->getRequest()->isSecure()], $params);
             return $this->_assetRepo->getUrlWithParams($fileId, $params);
         } catch (\Magento\Framework\Exception $e) {
-            $this->_logger->logException($e);
+            $this->_logger->critical($e);
             return $this->_getNotFoundUrl();
         }
     }
diff --git a/lib/internal/Magento/Framework/View/Element/Context.php b/lib/internal/Magento/Framework/View/Element/Context.php
index c908ec9fe3204973fd39b0b2d80a91bae9904109..c51fb19a835b2caeee4a8879b10736f4f4c32c6f 100644
--- a/lib/internal/Magento/Framework/View/Element/Context.php
+++ b/lib/internal/Magento/Framework/View/Element/Context.php
@@ -107,7 +107,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     /**
      * Logger
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -149,7 +149,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -171,7 +171,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
@@ -340,7 +340,7 @@ class Context implements \Magento\Framework\ObjectManager\ContextInterface
     /**
      * Get logger
      *
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/View/Element/Template.php b/lib/internal/Magento/Framework/View/Element/Template.php
index e4cc6b45156f93f63ecaad0add3c3c98caee3ddf..83f9c102cf2e32411a29ee1bb39bfb1dab7c4a89 100644
--- a/lib/internal/Magento/Framework/View/Element/Template.php
+++ b/lib/internal/Magento/Framework/View/Element/Template.php
@@ -251,7 +251,7 @@ class Template extends AbstractBlock
             $html = $templateEngine->render($this->templateContext, $fileName, $this->_viewVars);
         } else {
             $html = '';
-            $this->_logger->log("Invalid template file: '{$fileName}'", \Zend_Log::CRIT);
+            $this->_logger->info("Invalid template file: '{$fileName}'");
         }
 
         \Magento\Framework\Profiler::stop('TEMPLATE:' . $fileName);
diff --git a/lib/internal/Magento/Framework/View/Element/Template/Context.php b/lib/internal/Magento/Framework/View/Element/Template/Context.php
index e0578a46ec545346e8605d71a3a9cfb8c28ba3d4..1045d69095fc99eb155750c911a915b0e386167a 100644
--- a/lib/internal/Magento/Framework/View/Element/Template/Context.php
+++ b/lib/internal/Magento/Framework/View/Element/Template/Context.php
@@ -16,7 +16,7 @@ class Context extends \Magento\Framework\View\Element\Context
     /**
      * Logger instance
      *
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $_logger;
 
@@ -74,7 +74,7 @@ class Context extends \Magento\Framework\View\Element\Context
      * @param \Magento\Framework\View\Asset\Repository $assetRepo
      * @param \Magento\Framework\View\ConfigInterface $viewConfig
      * @param \Magento\Framework\App\Cache\StateInterface $cacheState
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Filter\FilterManager $filterManager
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
@@ -102,7 +102,7 @@ class Context extends \Magento\Framework\View\Element\Context
         \Magento\Framework\View\Asset\Repository $assetRepo,
         \Magento\Framework\View\ConfigInterface $viewConfig,
         \Magento\Framework\App\Cache\StateInterface $cacheState,
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Filter\FilterManager $filterManager,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
@@ -157,7 +157,7 @@ class Context extends \Magento\Framework\View\Element\Context
     /**
      * Get logger instance
      *
-     * @return \Magento\Framework\Logger
+     * @return \Psr\Log\LoggerInterface
      */
     public function getLogger()
     {
diff --git a/lib/internal/Magento/Framework/View/Layout/Data/Structure.php b/lib/internal/Magento/Framework/View/Layout/Data/Structure.php
index d9ae103f1620ffd416df7a70e59ea9d90405a737..cff15d3f74a968ee631cfad4019fec39214fe191 100644
--- a/lib/internal/Magento/Framework/View/Layout/Data/Structure.php
+++ b/lib/internal/Magento/Framework/View/Layout/Data/Structure.php
@@ -19,18 +19,18 @@ class Structure extends DataStructure
     protected $_nameIncrement = [];
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
     /**
      * Constructor
      *
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      * @param array $elements
      */
     public function __construct(
-        \Magento\Framework\Logger $logger,
+        \Psr\Log\LoggerInterface $logger,
         array $elements = null
     ) {
         $this->logger = $logger;
@@ -108,10 +108,9 @@ class Structure extends DataStructure
             if ($childName !== $sibling) {
                 $siblingParentName = $this->getParentId($sibling);
                 if ($parentName !== $siblingParentName) {
-                    $this->logger->log(
+                    $this->logger->info(
                         "Broken reference: the '{$childName}' tries to reorder itself towards '{$sibling}', but " .
-                        "their parents are different: '{$parentName}' and '{$siblingParentName}' respectively.",
-                        \Zend_Log::CRIT
+                        "their parents are different: '{$parentName}' and '{$siblingParentName}' respectively."
                     );
                     return;
                 }
diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/Block.php b/lib/internal/Magento/Framework/View/Layout/Generator/Block.php
index 3e632e331a6565f906892c75649844bd9092e3fa..1b192f422b044f3c407ea80f6d62f5f0d9f641bd 100644
--- a/lib/internal/Magento/Framework/View/Layout/Generator/Block.php
+++ b/lib/internal/Magento/Framework/View/Layout/Generator/Block.php
@@ -29,7 +29,7 @@ class Block implements Layout\GeneratorInterface
     protected $eventManager;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -39,13 +39,13 @@ class Block implements Layout\GeneratorInterface
      * @param \Magento\Framework\View\Element\BlockFactory $blockFactory
      * @param \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         \Magento\Framework\View\Element\BlockFactory $blockFactory,
         \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter,
         \Magento\Framework\Event\ManagerInterface $eventManager,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->blockFactory = $blockFactory;
         $this->argumentInterpreter = $argumentInterpreter;
@@ -172,7 +172,7 @@ class Block implements Layout\GeneratorInterface
             try {
                 $block = $this->blockFactory->createBlock($block, $arguments);
             } catch (\ReflectionException $e) {
-                $this->logger->log($e->getMessage());
+                $this->logger->critical($e->getMessage());
             }
         }
         if (!$block instanceof \Magento\Framework\View\Element\AbstractBlock) {
diff --git a/lib/internal/Magento/Framework/View/Layout/ScheduledStructure/Helper.php b/lib/internal/Magento/Framework/View/Layout/ScheduledStructure/Helper.php
index b5b5e5124814613863366b6a0703b0fb840dbe4c..e0258bdcff72ef31fc01c1411cc5977392a430a4 100644
--- a/lib/internal/Magento/Framework/View/Layout/ScheduledStructure/Helper.php
+++ b/lib/internal/Magento/Framework/View/Layout/ScheduledStructure/Helper.php
@@ -26,15 +26,15 @@ class Helper
     protected $counter = 0;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
     /**
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->logger = $logger;
     }
@@ -169,7 +169,7 @@ class Helper
         $data = $scheduledStructure->getStructureElementData($key);
         // if we have reference container to not existed element
         if (!isset($row[self::SCHEDULED_STRUCTURE_INDEX_TYPE])) {
-            $this->logger->log("Broken reference: missing declaration of the element '{$key}'.", \Zend_Log::CRIT);
+            $this->logger->info("Broken reference: missing declaration of the element '{$key}'.");
             $scheduledStructure->unsetPathElement($key);
             $scheduledStructure->unsetStructureElement($key);
             return;
@@ -185,13 +185,12 @@ class Helper
                 try {
                     $structure->setAsChild($name, $parentName, $alias);
                 } catch (\Exception $e) {
-                    $this->logger->log($e->getMessage());
+                    $this->logger->critical($e);
                 }
             } else {
-                $this->logger->log(
+                $this->logger->info(
                     "Broken reference: the '{$name}' element cannot be added as child to '{$parentName}', " .
-                    'because the latter doesn\'t exist',
-                    \Zend_Log::CRIT
+                    'because the latter doesn\'t exist'
                 );
             }
         }
diff --git a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php
index 44d388ed1aa773a37e660d45745fa79540746273..5edeba40ea2db7fbe6c1054859c8692302c0c461 100644
--- a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php
+++ b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php
@@ -39,7 +39,7 @@ class Renderer
     protected $string;
 
     /**
-     * @var \Magento\Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -55,7 +55,7 @@ class Renderer
      * @param \Magento\Framework\UrlInterface $urlBuilder
      * @param \Magento\Framework\Escaper $escaper
      * @param \Magento\Framework\Stdlib\String $string
-     * @param \Magento\Framework\Logger $logger
+     * @param \Psr\Log\LoggerInterface $logger
      */
     public function __construct(
         Config $pageConfig,
@@ -64,7 +64,7 @@ class Renderer
         \Magento\Framework\UrlInterface $urlBuilder,
         \Magento\Framework\Escaper $escaper,
         \Magento\Framework\Stdlib\String $string,
-        \Magento\Framework\Logger $logger
+        \Psr\Log\LoggerInterface $logger
     ) {
         $this->pageConfig = $pageConfig;
         $this->assetMinifyService = $assetMinifyService;
@@ -339,7 +339,7 @@ class Renderer
                 $result .= sprintf($template, $asset->getUrl());
             }
         } catch (\Magento\Framework\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             $result .= sprintf($template, $this->urlBuilder->getUrl('', ['_direct' => 'core/index/notFound']));
         }
         return $result;
diff --git a/lib/internal/Magento/Framework/View/Result/Page.php b/lib/internal/Magento/Framework/View/Result/Page.php
index c5435e9c4ceb7ec20ddc87da21785c8ea272792c..4ddaf6f9144015d950040bf3b91199f0eae9e71d 100644
--- a/lib/internal/Magento/Framework/View/Result/Page.php
+++ b/lib/internal/Magento/Framework/View/Result/Page.php
@@ -78,7 +78,7 @@ class Page extends Layout
     protected $assetRepo;
 
     /**
-     * @var Framework\Logger
+     * @var \Psr\Log\LoggerInterface
      */
     protected $logger;
 
@@ -327,7 +327,7 @@ class Page extends Layout
             $params = array_merge(['_secure' => $this->request->isSecure()], $params);
             return $this->assetRepo->getUrlWithParams($fileId, $params);
         } catch (\Magento\Framework\Exception $e) {
-            $this->logger->logException($e);
+            $this->logger->critical($e);
             return $this->urlBuilder->getUrl('', ['_direct' => 'core/index/notFound']);
         }
     }
diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json
index e118f4730d5fbdd9dc669f581ea342c4fa75906b..2d0570bae3b5db64568217c4183adbca116fce83 100644
--- a/lib/internal/Magento/Framework/composer.json
+++ b/lib/internal/Magento/Framework/composer.json
@@ -2,7 +2,7 @@
     "name": "magento/framework",
     "description": "N/A",
     "type": "magento2-library",
-    "version": "0.42.0-beta1",
+    "version": "0.42.0-beta2",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
diff --git a/pub/errors/processorFactory.php b/pub/errors/processorFactory.php
index ba61ce6a9fa5b77f973d2a72b09d04f13810c269..62b5330f8052c7488db8acb2994119a1a760cefc 100644
--- a/pub/errors/processorFactory.php
+++ b/pub/errors/processorFactory.php
@@ -21,7 +21,7 @@ class ProcessorFactory
     {
         $objectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER);
         $objectManager = $objectManagerFactory->create($_SERVER);
-        $response = $objectManager->create('\Magento\Framework\App\Response\Http');
+        $response = $objectManager->create('Magento\Framework\App\Response\Http');
         return new Processor($response);
     }
 }
diff --git a/success.png b/success.png
deleted file mode 100644
index c2853cfc0cbb8856e5baa894332e6f4063428c80..0000000000000000000000000000000000000000
Binary files a/success.png and /dev/null differ
diff --git a/success_admin.png b/success_admin.png
deleted file mode 100644
index 0901763600a4271438c4b604df881ba079dc934f..0000000000000000000000000000000000000000
Binary files a/success_admin.png and /dev/null differ