From 974d259df65aef731626aa41228e76c3763235b3 Mon Sep 17 00:00:00 2001
From: mage2-team <mage2-team@magento.com>
Date: Fri, 27 Jun 2014 11:04:08 -0700
Subject: [PATCH] 2.0.0.0-dev84 * Fixed bugs:   * Fixed an issue where an
 invalidly filled option did not become in focus after saving attempt on the
 Create New Order page in the backend   * Fixed an issue with the default
 configuration not being applied properly in the CAPTCHA configuration section
   * Fixed an issue with optional State/Province fields on the Create New
 Order page being marked as required   * Fixed an issue with incorrect
 Customer model usage on session in community modules   * Fixed an issue where
 cache was not invalidated after applying catalog price rule   * Fixed an
 issue where an admin with custom permissions could not create Shopping Cart
 Price Rule/Catalog Price Rule   * Fixed an issue with REST request and
 response format being inconsistent   * Fixed an issue where there was an
 error on a bundle product page if bundle items contained an out of stock
 product   * Fixed a JS issue which appeared when adding associated products
 for a grouped product   * Fixed an issue where layered navigation was absent
 on the Advanced Search results page   * Fixed an issue where the leading "0"
 in numbers were truncated when exporting using Excel XML   * Fixed the price
 type attribute filter in Layered Navigation   * Fixed an issue with a fatal
 error in \Magento\Framework\ArchiveTest when bz2 extension was not installed 
  * Fixed an issue where an admin could search product by attributes set on
 the Store View level (except default store view)   * Fixed an issue where
 extra spaces in search values were not ignored during search and thus wrong
 search results were given * GitHub requests:   * [#542]  Fix ImportExport bug
 which occurs while importing multiple rows per entity   * [#544]  Performance
 tests not working * Framework improvements:   * Covered the following Magento
 application components with unit tests:       * `Customer/Model/Address.php` 
      * `Customer/Model/Address/AbstractAddress.php `       *
 `Customer/Model/Address/Converter.php`       * `Customer/Model/Customer.php` 
      * `Customer/Model/Customer/Attribute/Backend/Billing.php`       *
 `Customer/Model/Customer/Attribute/Backend/Shipping.php`       *
 `Customer/Model/Customer/Attribute/Backend/Store.php `       *
 `Customer/Model/Customer/Attribute/Backend/Website.php `       *
 `Customer/Model/Customer/Attribute/Backend/PasswordTest.php`       *
 `Customer/Helper/Address.php`       * `Customer/Helper/View.php`       *
 `Customer/Service/V1/CustomerAccountService.php`   * Covered Magento lib with
 unit tests:       * `lib/internal/Magento/Framework/Filter/*`       *
 `lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php`       *
 `lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php`
       * `lib/internal/Magento/Framework/File/Uploader.php`       *
 `lib/internal/Magento/Framework/File/Csv.php`       *
 `lib/internal/Magento/Framework/Less/File/Collector/Aggregated.php`       *
 `lib/internal/Magento/Framework/Less/File/Collector/Library.php`       *
 `lib/internal/Magento/Framework/Locale/Config.php`       *
 `lib/internal/Magento/Framework/Locale/Currency.php`       *
 `lib/internal/Magento/Framework/App/Config/Element.php`       *
 `lib/internal/Magento/Framework/App/Config/Value.php`       *
 `lib/internal/Magento/Framework/App/DefaultPath/DefaultPath.php`       *
 `lib/internal/Magento/Framework/App/EntryPoint/EntryPoint.php`       *
 `lib/internal/Magento/Framework/App/Helper/AbstractHelper.php`       *
 `lib/internal/Magento/Framework/App/Resource/ConnectionFactory.php`       *
 `lib/internal/Magento/Framework/App/Route/Config.php`   * Implemented the
 ability for a mobile client to get a partial response   * Added
 authentication support for mobile   * Refactored the Oauth lib exception not
 to reference module classes   * Moved the authorization services according to
 the new directory format: was
 \Magento\Authz\Service\AuthorizationV1Interface, became
 \Magento\Authz\Service\V1\AuthorizationInterface   * Moved the integration
 services according to the new directory format:     * Was
 \Magento\Integration\Service\IntegrationV1, became
 \Magento\Integration\Service\V1\Integration     * Was
 \Magento\Integration\Service\OauthV1, became
 \Magento\Integration\Service\V1\Oauth   * Improved security of the
 integration registration   * Introduced language packages with ability to
 inherit dictionaries * Improved modularity of ImportExport * Created Service
 API for Magento_Catalog module:    * Implemented Product Attribute Media API 
   * Implemented Product Group Price API    * Implemented Product Attribute
 Write API    * Implemented Product Attribute Options Read and Write API *
 Created Service for the Magento Tax module:   * Implemented Tax Rule Service 
  * Implemented Tax Rate Service   * Implemented Tax Calculation Data Objects 
  * Implemented Tax Calculation Builders   * Implemented Tax Calculation
 Service * Covered the part of the Catalog Module with unit tests * Added
 PayPall Bill Me Later button * Streamlined checkout experience * Improved
 order review page for PayPal Express Checkout

---
 CHANGELOG.md                                  |   80 +-
 .../Magento/AdminNotification/etc/module.xml  |    2 +-
 app/code/Magento/Authorizenet/etc/module.xml  |    2 +-
 .../Magento/Authz/Service/AuthorizationV1.php |  141 ++-
 app/code/Magento/Authz/etc/module.xml         |    5 +-
 .../Magento/Backend/Block/Widget/Grid.php     |   11 -
 app/code/Magento/Backend/Helper/Data.php      |   25 +-
 .../Magento/Backend/Model/Search/Catalog.php  |    2 +-
 app/code/Magento/Backend/etc/module.xml       |    2 +-
 app/code/Magento/Backup/etc/module.xml        |    2 +-
 .../Bundle/Pricing/Adjustment/Calculator.php  |    6 +-
 app/code/Magento/Bundle/etc/module.xml        |    2 +-
 app/code/Magento/Captcha/etc/module.xml       |    2 +-
 .../Category/Attribute/Backend/Sortby.php     |   55 +-
 .../Model/Category/Attribute/Source/Mode.php  |    1 +
 .../Catalog/Model/Config/Source/ListMode.php  |    2 +
 .../Model/Config/Source/Price/Scope.php       |    2 +
 .../Model/Config/Source/Price/Step.php        |    2 +
 .../Config/Source/Product/Options/Price.php   |    2 +
 .../Model/Config/Source/Product/Thumbnail.php |    2 +
 .../Model/Config/Source/TimeFormat.php        |    2 +
 .../Config/Source/Watermark/Position.php      |    1 +
 .../Catalog/Model/Layer/Filter/Decimal.php    |    4 +-
 .../Catalog/Model/Layer/Filter/Price.php      |    2 +-
 .../Magento/Catalog/Model/Layer/State.php     |   16 +-
 app/code/Magento/Catalog/Model/Product.php    |    2 +-
 .../Model/Product/Attribute/Backend/Media.php |    4 +-
 .../Product/Attribute/Frontend/Image.php      |   14 +-
 .../Catalog/Model/Product/Condition.php       |   10 +-
 .../Magento/Catalog/Model/Product/Option.php  |   21 -
 .../Catalog/Model/Product/Option/Value.php    |   13 -
 .../Magento/Catalog/Model/Product/Type.php    |   11 +-
 .../Model/Product/Type/AbstractType.php       |    4 +-
 .../Catalog/Service/V1/Data/Eav/Attribute.php |   11 +
 .../Service/V1/Data/Eav/AttributeBuilder.php  |   11 +
 .../Service/V1/Data/Eav/AttributeMetadata.php |   98 +-
 .../V1/Data/Eav/AttributeMetadataBuilder.php  |   65 +-
 .../Catalog/Service/V1/Data/Eav/Option.php    |   38 +-
 .../Service/V1/Data/Eav/Option/Label.php      |   58 +
 .../V1/Data/Eav/Option/LabelBuilder.php       |   52 +
 .../Service/V1/Data/Eav/OptionBuilder.php     |   33 +
 .../Eav/Product/Attribute/FrontendLabel.php   |   58 +
 .../Attribute/FrontendLabelBuilder.php        |   53 +
 .../Product/Attribute/Type.php}               |    8 +-
 .../Product/Attribute/TypeBuilder.php}        |   12 +-
 .../Data/Product/Attribute/SearchResults.php  |   41 +
 .../Attribute/SearchResultsBuilder.php        |   64 +
 .../Service/V1/Data/Product/SearchResults.php |   41 +
 .../V1/Data/Product/SearchResultsBuilder.php  |   64 +
 .../V1/Product/Attribute/ReadService.php      |  227 ++++
 .../Attribute/ReadServiceInterface.php        |   56 +
 .../V1/Product/Attribute/WriteService.php     |  234 ++++
 .../Attribute/WriteServiceInterface.php       |   62 +
 .../V1/Product/AttributeSet/ReadService.php   |    1 +
 .../V1/ProductAttributeReadService.php        |   88 --
 .../Service/V1/ProductAttributeService.php    |  109 ++
 ...p => ProductAttributeServiceInterface.php} |   25 +-
 .../Service/V1/ProductMetadataService.php     |   33 +-
 .../Catalog/Service/V1/ProductService.php     |    6 +-
 .../Service/V1/ProductServiceInterface.php    |    4 +-
 app/code/Magento/Catalog/etc/di.xml           |    8 +-
 app/code/Magento/Catalog/etc/module.xml       |    3 +-
 app/code/Magento/Catalog/etc/webapi.xml       |   40 +-
 app/code/Magento/Catalog/i18n/de_DE.csv       |    2 +
 app/code/Magento/Catalog/i18n/en_US.csv       |    2 +
 app/code/Magento/Catalog/i18n/es_ES.csv       |    2 +
 app/code/Magento/Catalog/i18n/fr_FR.csv       |    2 +
 app/code/Magento/Catalog/i18n/nl_NL.csv       |    2 +
 app/code/Magento/Catalog/i18n/pt_BR.csv       |    2 +
 app/code/Magento/Catalog/i18n/zh_CN.csv       |    2 +
 .../Model/Export}/Product.php                 |   18 +-
 .../Export}/Product/Type/AbstractType.php     |    2 +-
 .../Export}/Product/Type/Configurable.php     |    4 +-
 .../Model/Export}/Product/Type/Factory.php    |    4 +-
 .../Model/Export}/Product/Type/Grouped.php    |    4 +-
 .../Model/Export}/Product/Type/Simple.php     |    4 +-
 .../Model/Export/RowCustomizer.php            |    4 +-
 .../Model/Export/RowCustomizer/Composite.php  |    4 +-
 .../Model/Export/RowCustomizerInterface.php   |    2 +-
 .../Model/Import}/Product.php                 |   46 +-
 .../Model/Import}/Product/Option.php          |    4 +-
 .../Import}/Product/Type/AbstractType.php     |   16 +-
 .../Import}/Product/Type/Configurable.php     |   12 +-
 .../Model/Import}/Product/Type/Factory.php    |    4 +-
 .../Model/Import}/Product/Type/Grouped.php    |   16 +-
 .../Model/Import}/Product/Type/Simple.php     |    4 +-
 .../Model/Import/Proxy/Product.php            |    2 +-
 .../Model/Import/Proxy/Product/Resource.php   |    2 +-
 .../Model/Import/Uploader.php                 |    2 +-
 .../Indexer/Product/Flat/Plugin/Import.php    |    2 +-
 .../Indexer/Product/Price/Plugin/Import.php   |    4 +-
 .../etc/config.xml}                           |    7 +-
 .../Magento/CatalogImportExport/etc/di.xml    |   39 +
 .../etc/export.xml                            |    8 +-
 .../etc/import.xml                            |   11 +-
 .../CatalogImportExport/etc/module.xml        |   40 +
 .../Magento/CatalogInventory/etc/module.xml   |    2 +-
 .../Magento/CatalogRule/etc/adminhtml/di.xml  |    1 +
 app/code/Magento/CatalogRule/etc/module.xml   |    2 +-
 .../CatalogSearch/Controller/Advanced.php     |   10 +-
 .../Magento/CatalogSearch/Model/Advanced.php  |   65 +-
 .../CatalogSearch/Model/Layer/Advanced.php    |   65 ++
 .../Model/Layer/Advanced/CollectionFilter.php |   91 ++
 .../Model/Layer/Advanced/Context.php          |   41 +
 .../Advanced/FilterableAttributeList.php      |   52 +
 .../Layer/Advanced/ItemCollectionProvider.php |   57 +
 .../Model/Resource/Search/Collection.php      |   35 +-
 app/code/Magento/CatalogSearch/etc/di.xml     |   10 +
 app/code/Magento/CatalogSearch/etc/module.xml |    2 +-
 app/code/Magento/Centinel/etc/module.xml      |    2 +-
 app/code/Magento/Checkout/etc/module.xml      |    2 +-
 .../Magento/CheckoutAgreements/etc/module.xml |    2 +-
 app/code/Magento/Cms/etc/module.xml           |    2 +-
 .../Magento/ConfigurableProduct/etc/di.xml    |    7 -
 .../ConfigurableProduct/etc/module.xml        |    3 +-
 app/code/Magento/Connect/etc/module.xml       |    2 +-
 app/code/Magento/Contact/etc/module.xml       |    2 +-
 app/code/Magento/Core/etc/di.xml              |    5 -
 app/code/Magento/Core/etc/module.xml          |    2 +-
 app/code/Magento/Cron/etc/module.xml          |    2 +-
 .../Magento/CurrencySymbol/etc/module.xml     |    2 +-
 .../Customer/Controller/Adminhtml/Index.php   |   33 -
 .../Model/Address/AbstractAddress.php         |   28 +-
 .../Customer/Model/Address/Converter.php      |   17 +-
 app/code/Magento/Customer/Model/Converter.php |   17 +-
 app/code/Magento/Customer/Model/Customer.php  |   30 +-
 .../Customer/Service/V1/Data/Address.php      |    8 +-
 .../Service/V1/Data/SearchResults.php         |   24 +-
 .../Service/V1/Data/SearchResultsBuilder.php  |   43 +-
 app/code/Magento/Customer/etc/config.xml      |    6 -
 app/code/Magento/Customer/etc/module.xml      |    3 +-
 app/code/Magento/Customer/etc/webapi.xml      |   11 +-
 .../layout/customer_index_grid_block.xml      |   14 -
 .../Controller/Adminhtml/Index.php            |   82 ++
 .../Model}/Export/Address.php                 |    6 +-
 .../Model}/Export/Customer.php                |    2 +-
 .../Model}/Import/AbstractCustomer.php        |   10 +-
 .../Model}/Import/Address.php                 |    6 +-
 .../Model}/Import/Customer.php                |    6 +-
 .../Model}/Import/CustomerComposite.php       |   18 +-
 .../Resource}/Import/Customer/Storage.php     |    2 +-
 .../Import/CustomerComposite/Data.php         |    4 +-
 .../etc/adminhtml/routes.xml}                 |   10 +-
 .../etc/config.xml}                           |   11 +-
 .../etc/export.xml                            |    4 +-
 .../etc/import.xml                            |    6 +-
 .../CustomerImportExport/etc/module.xml       |   38 +
 ...ustomer_import_export_index_exportcsv.xml} |    0
 ...ustomer_import_export_index_exportxml.xml} |    0
 .../layout/customer_index_grid_block.xml      |   44 +
 app/code/Magento/DesignEditor/etc/module.xml  |    2 +-
 app/code/Magento/Dhl/etc/module.xml           |    2 +-
 app/code/Magento/Directory/etc/module.xml     |    2 +-
 app/code/Magento/Downloadable/etc/module.xml  |    2 +-
 .../Entity/Attribute/AbstractAttribute.php    |    4 +-
 app/code/Magento/Eav/etc/module.xml           |    2 +-
 app/code/Magento/Email/etc/module.xml         |    2 +-
 app/code/Magento/Fedex/etc/module.xml         |    2 +-
 app/code/Magento/GiftMessage/etc/module.xml   |    2 +-
 app/code/Magento/GoogleAdwords/etc/module.xml |    2 +-
 .../Magento/GoogleAnalytics/etc/module.xml    |    2 +-
 .../Magento/GoogleOptimizer/etc/module.xml    |    2 +-
 .../Magento/GoogleShopping/etc/module.xml     |    2 +-
 .../Magento/GroupedProduct/etc/module.xml     |    3 +-
 app/code/Magento/ImportExport/Helper/Data.php |    2 +-
 .../ImportExport/Model/Export/Config.php      |    8 +-
 .../Model/Export/Config/Converter.php         |   30 +-
 .../Model/Export/Config/Reader.php            |    2 +-
 .../Model/Export/ConfigInterface.php          |    5 +-
 .../Magento/ImportExport/Model/Import.php     |   75 +-
 .../ImportExport/Model/Import/Config.php      |   20 +-
 .../Model/Import/Config/Converter.php         |   38 +-
 .../Model/Import/Config/Reader.php            |    6 +-
 .../Model/Import/ConfigInterface.php          |   13 +-
 .../Model/Import/Entity/AbstractEntity.php    |    8 +-
 app/code/Magento/ImportExport/etc/di.xml      |    1 -
 app/code/Magento/ImportExport/etc/export.xsd  |   17 +-
 app/code/Magento/ImportExport/etc/import.xsd  |   27 +-
 app/code/Magento/ImportExport/etc/module.xml  |    8 +-
 app/code/Magento/ImportExport/i18n/de_DE.csv  |    2 -
 app/code/Magento/ImportExport/i18n/en_US.csv  |    2 -
 app/code/Magento/ImportExport/i18n/es_ES.csv  |    2 -
 app/code/Magento/ImportExport/i18n/fr_FR.csv  |    2 -
 app/code/Magento/ImportExport/i18n/nl_NL.csv  |    2 -
 app/code/Magento/ImportExport/i18n/pt_BR.csv  |    2 -
 app/code/Magento/ImportExport/i18n/zh_CN.csv  |    2 -
 .../importexport_setup/install-1.6.0.0.php    |   38 -
 app/code/Magento/Index/etc/module.xml         |    2 +-
 app/code/Magento/Indexer/etc/module.xml       |    2 +-
 app/code/Magento/Install/etc/module.xml       |    2 +-
 .../Widget/Grid/Column/Renderer/Name.php      |   47 +
 .../Controller/Adminhtml/Integration.php      |   23 +-
 .../Magento/Integration/Controller/Token.php  |    4 +-
 .../Magento/Integration/Model/Manager.php     |    6 +-
 .../Model/Oauth/Nonce/Generator.php           |   12 +-
 .../Magento/Integration/Model/Oauth/Token.php |   10 +-
 .../Model/Oauth/Token/Provider.php            |   59 +-
 .../Model/Resource/Integration/Collection.php |   10 +
 .../{IntegrationV1.php => V1/Integration.php} |    6 +-
 .../IntegrationInterface.php}                 |    4 +-
 .../Service/{OauthV1.php => V1/Oauth.php}     |   13 +-
 .../OauthInterface.php}                       |    4 +-
 app/code/Magento/Integration/etc/di.xml       |    4 +-
 app/code/Magento/Integration/etc/module.xml   |    2 +-
 .../adminhtml_integration_grid_block.xml      |    1 +
 .../view/adminhtml/web/js/integration.js      |    4 +
 .../LayeredNavigation/etc/frontend/di.xml     |   12 +
 .../Magento/LayeredNavigation/etc/module.xml  |    2 +-
 .../layout/catalogsearch_advanced_result.xml  |   33 +
 app/code/Magento/Log/etc/module.xml           |    2 +-
 app/code/Magento/Multishipping/etc/module.xml |    2 +-
 app/code/Magento/Newsletter/etc/module.xml    |    2 +-
 .../Magento/OfflinePayments/etc/module.xml    |    2 +-
 .../Magento/OfflineShipping/etc/module.xml    |    2 +-
 app/code/Magento/Ogone/etc/module.xml         |    2 +-
 app/code/Magento/PageCache/etc/module.xml     |    2 +-
 .../PayPalRecurringPayment/Model/Api/Nvp.php  |    9 +
 .../PayPalRecurringPayment/etc/module.xml     |    2 +-
 app/code/Magento/Payment/etc/module.xml       |    2 +-
 .../Adminhtml/System/Config/ApiWizard.php     |    7 +-
 .../Adminhtml/System/Config/BmlApiWizard.php  |   52 +
 .../System/Config/Fieldset/Location.php       |   30 +
 app/code/Magento/Paypal/Block/Bml/Banners.php |   80 ++
 app/code/Magento/Paypal/Block/Bml/Form.php    |   56 +
 .../Magento/Paypal/Block/Bml/Shortcut.php     |  196 ++++
 .../Magento/Paypal/Block/Express/Review.php   |    6 +-
 .../Magento/Paypal/Block/Express/Shortcut.php |  111 +-
 .../Magento/Paypal/Block/Payflow/Bml/Form.php |   37 +
 .../Magento/Paypal/Block/Standard/Form.php    |   54 +-
 app/code/Magento/Paypal/Controller/Bml.php    |   41 +
 .../Controller/Express/AbstractExpress.php    |  124 +-
 .../Magento/Paypal/Controller/Payflowbml.php  |   41 +
 .../Helper/Shortcut/CheckoutValidator.php     |  110 ++
 .../Paypal/Helper/Shortcut/Factory.php        |   64 +
 .../Paypal/Helper/Shortcut/Validator.php      |  145 +++
 .../Helper/Shortcut/ValidatorInterface.php    |   37 +
 app/code/Magento/Paypal/Model/Api/Nvp.php     |  162 ++-
 .../Magento/Paypal/Model/Api/PayflowNvp.php   |   17 +-
 .../Paypal/Model/Api/ProcessableException.php |   64 +
 app/code/Magento/Paypal/Model/Bml.php         |   50 +
 app/code/Magento/Paypal/Model/Config.php      |  273 ++++-
 app/code/Magento/Paypal/Model/Express.php     |   73 +-
 .../Magento/Paypal/Model/Express/Checkout.php |  180 ++-
 app/code/Magento/Paypal/Model/Observer.php    |   68 +-
 .../Shortcut.php => Model/Payflow/Bml.php}    |   30 +-
 .../Magento/Paypal/Model/PayflowExpress.php   |    6 +
 app/code/Magento/Paypal/Model/Payflowlink.php |    4 +-
 app/code/Magento/Paypal/Model/Payflowpro.php  |    5 +
 .../System/Config/Source/BmlPosition.php      |   80 ++
 .../Model/System/Config/Source/BmlSize.php    |  163 +++
 .../Magento/Paypal/etc/adminhtml/system.xml   |  694 ++++++++++-
 app/code/Magento/Paypal/etc/config.xml        |   12 +
 app/code/Magento/Paypal/etc/di.xml            |   33 +
 app/code/Magento/Paypal/etc/module.xml        |    2 +-
 .../system/config/bml_api_wizard.phtml        |   34 +
 .../frontend/layout/catalog_category_view.xml |   16 +-
 .../frontend/layout/catalog_product_view.xml  |   43 +
 .../frontend/layout/checkout_cart_index.xml   |   43 +
 .../layout/checkout_onepage_index.xml         |    8 +
 .../view/frontend/layout/cms_index_index.xml  |   14 +
 .../frontend/layout/paypal_express_review.xml |    4 -
 .../layout/paypal_payflowexpress_review.xml   |    4 +-
 .../Paypal/view/frontend/templates/bml.phtml  |   38 +
 .../frontend/templates/express/review.phtml   |  158 ++-
 .../templates/express/review/address.phtml    |  194 ----
 .../frontend/templates/express/shortcut.phtml |   10 +-
 .../templates/payflowexpress/review.phtml     |  158 ---
 .../frontend/templates/payment/mark.phtml     |    4 +-
 app/code/Magento/Persistent/etc/module.xml    |    2 +-
 app/code/Magento/ProductAlert/etc/module.xml  |    2 +-
 .../Magento/RecurringPayment/etc/module.xml   |    2 +-
 .../Controller/Adminhtml/Report/Sales.php     |    1 +
 .../Magento/Reports/Model/Event/Observer.php  |    3 +-
 app/code/Magento/Reports/etc/module.xml       |    2 +-
 app/code/Magento/RequireJs/etc/module.xml     |    2 +-
 app/code/Magento/Review/etc/module.xml        |    2 +-
 app/code/Magento/Rss/etc/module.xml           |    2 +-
 app/code/Magento/Rule/etc/module.xml          |    2 +-
 .../Magento/Sales/Block/Order/History.php     |    2 +-
 app/code/Magento/Sales/Block/Order/Recent.php |    2 +-
 app/code/Magento/Sales/etc/module.xml         |    2 +-
 app/code/Magento/SalesRule/etc/module.xml     |    2 +-
 app/code/Magento/Sendfriend/etc/module.xml    |    2 +-
 app/code/Magento/Shipping/etc/module.xml      |    2 +-
 app/code/Magento/Sitemap/etc/module.xml       |    2 +-
 app/code/Magento/Store/etc/module.xml         |    2 +-
 app/code/Magento/Tax/Model/Calculation.php    |   15 +-
 .../Tax/Model/Calculation/Rate/Converter.php  |  136 +++
 .../Tax/Model/Calculation/RateRegistry.php    |  101 ++
 .../Model/Calculation/TaxRuleConverter.php    |  113 ++
 .../Tax/Model/Calculation/TaxRuleRegistry.php |   94 ++
 .../Tax/Service/V1/Data/QuoteDetails.php      |   80 ++
 .../Tax/Service/V1/Data/QuoteDetails/Item.php |  139 +++
 .../V1/Data/QuoteDetails/ItemBuilder.php      |  131 +++
 .../Service/V1/Data/QuoteDetailsBuilder.php   |  125 ++
 .../Tax/Service/V1/Data/TaxDetails.php        |   93 ++
 .../Service/V1/Data/TaxDetails/AppliedTax.php |   54 +-
 .../V1/Data/TaxDetails/AppliedTaxBuilder.php  |  112 ++
 .../V1/Data/TaxDetails/AppliedTaxRate.php     |   68 ++
 .../TaxDetails/AppliedTaxRateBuilder.php}     |   35 +-
 .../Tax/Service/V1/Data/TaxDetails/Item.php   |  164 +++
 .../V1/Data/TaxDetails/ItemBuilder.php        |  195 ++++
 .../Tax/Service/V1/Data/TaxDetailsBuilder.php |  152 +++
 .../Magento/Tax/Service/V1/Data/TaxRate.php   |  115 ++
 .../Tax/Service/V1/Data/TaxRateBuilder.php    |  151 +++
 .../Magento/Tax/Service/V1/Data/TaxRule.php   |  121 ++
 .../Tax/Service/V1/Data/TaxRuleBuilder.php    |  132 +++
 .../Service/V1/Data/TaxRuleSearchResults.php  |   43 +
 .../V1/Data/TaxRuleSearchResultsBuilder.php   |   63 +
 .../Magento/Tax/Service/V1/Data/ZipRange.php  |   33 +-
 .../Tax/Service/V1/Data/ZipRangeBuilder.php   |   56 +
 .../Tax/Service/V1/TaxCalculationService.php  |  583 ++++++++++
 .../V1/TaxCalculationServiceInterface.php     |   37 +
 .../Magento/Tax/Service/V1/TaxRateService.php |  189 +++
 .../Service/V1/TaxRateServiceInterface.php    |   68 ++
 .../Magento/Tax/Service/V1/TaxRuleService.php |  194 ++++
 .../Service/V1/TaxRuleServiceInterface.php    |   79 ++
 app/code/Magento/Tax/etc/di.xml               |    6 +
 app/code/Magento/Tax/etc/module.xml           |    2 +-
 app/code/Magento/Theme/etc/module.xml         |    2 +-
 app/code/Magento/Translation/etc/module.xml   |    2 +-
 app/code/Magento/Ups/etc/module.xml           |    2 +-
 app/code/Magento/UrlRewrite/etc/module.xml    |    2 +-
 app/code/Magento/User/etc/module.xml          |    2 +-
 app/code/Magento/Usps/etc/module.xml          |    2 +-
 app/code/Magento/Webapi/Controller/Login.php  |  145 +++
 app/code/Magento/Webapi/Controller/Rest.php   |  119 +-
 .../Webapi/Controller/Rest/Response.php       |    4 +-
 .../Response/PartialResponseProcessor.php     |  204 ++++
 .../Rest/Response/Renderer/Json.php           |    2 +-
 .../Controller/Rest/Response/Renderer/Xml.php |    2 +-
 .../Rest/Response/RendererInterface.php       |    2 +-
 .../Controller/Soap/Request/Handler.php       |   10 +-
 .../Magento/Webapi/Model/Config/Converter.php |   15 +-
 .../Model/Plugin/AuthorizationServiceV1.php   |    2 +-
 .../Model/Plugin/IntegrationServiceV1.php     |   18 +-
 .../Magento/Webapi/Model/Plugin/Setup.php     |    6 +-
 app/code/Magento/Webapi/Model/Soap/Config.php |    2 +-
 app/code/Magento/Webapi/etc/di.xml            |   24 +-
 .../etc/frontend/routes.xml}                  |    8 +-
 app/code/Magento/Webapi/etc/module.xml        |    3 +-
 app/code/Magento/Webapi/etc/webapi.xsd        |    4 +-
 .../Magento/Webapi/etc/webapi_rest/di.xml     |   27 +-
 app/code/Magento/Weee/etc/module.xml          |    2 +-
 app/code/Magento/Widget/etc/module.xml        |    2 +-
 app/code/Magento/Wishlist/etc/module.xml      |    2 +-
 .../Magento_Theme/web/css/source/module.less  |   23 +
 .../adminhtml/Magento/backend/theme.xml       |    2 +-
 app/design/frontend/Magento/blank/theme.xml   |    2 +-
 app/design/frontend/Magento/plushe/theme.xml  |    2 +-
 app/design/install/Magento/basic/theme.xml    |    2 +-
 .../i18n/Magento/de_DE/language.xml           |    6 +-
 .../i18n/Magento/en_US/language.xml           |    6 +-
 app/i18n/Magento/es_ES/language.xml           |   29 +
 app/i18n/Magento/fr_FR/language.xml           |   29 +
 app/i18n/Magento/nl_NL/language.xml           |   29 +
 app/i18n/Magento/pt_BR/language.xml           |   29 +
 app/i18n/Magento/zh_CN/language.xml           |   29 +
 dev/tests/functional/bootstrap.php            |    1 +
 .../Element/MultiselectgrouplistElement.php   |    1 +
 .../Client/Driver/Selenium/Element/Tree.php   |    3 +-
 .../lib/Mtf/ObjectManagerFactory.php          |   12 +-
 .../functional/lib/Mtf/Page/BackendPage.php   |    1 +
 .../Util/Generate/Factory/AbstractFactory.php |    4 +-
 .../Mtf/Util/Generate/Repository/Resource.php |    1 +
 .../lib/Mtf/Util/Generate/TestCase.php        |    3 +
 .../lib/Mtf/Util/Protocol/CurlInterface.php   |    4 +-
 .../lib/Mtf/Util/Protocol/CurlTransport.php   |   12 +-
 .../CurlTransport/BackendDecorator.php        |    6 +-
 .../Backend/Test/Block/Widget/Form.php        |    4 +
 .../Backend/Test/Block/Widget/FormTabs.php    |    7 +
 .../Backend/Test/Block/Widget/Grid.php        |    2 +
 .../Magento/Backend/Test/Block/Widget/Tab.php |    2 +
 .../app/Magento/Backend/Test/Fixture/Date.php |    2 +
 .../Backend/Test/Handler/Ui/LogoutUser.php    |    2 +
 .../Product/Edit/Tab/Bundle/Option.php        |    2 +
 .../Bundle/Test/Fixture/Bundle/Price.php      |    2 +
 .../Bundle/Test/Fixture/Bundle/Selections.php |    3 +
 .../Bundle/Test/Fixture/BundleFixed.php       |    2 +
 .../Test/Fixture/CatalogProductBundle.php     |    3 +
 .../Test/Repository/CatalogProductBundle.php  |    6 +
 .../Product/AffectedAttributeSetForm.php      |    3 +-
 .../Test/Block/Product/View/CustomOptions.php |    2 +
 .../app/Magento/Catalog/Test/Block/Search.php |    2 +
 .../Test/Constraint/AssertProductForm.php     |    2 +
 .../Catalog/Test/Fixture/CatalogCategory.php  |    2 +
 .../Test/Fixture/CatalogProductAttribute.php  |    2 +
 .../CatalogProductAttribute/Options.php       |    2 +
 .../Test/Fixture/CatalogProductSimple.php     |    3 +
 .../CatalogProductSimple/CategoryIds.php      |    2 +
 .../CatalogProductSimple/CustomOptions.php    |    4 +
 .../GroupPriceOptions.php                     |    2 +
 .../Fixture/CatalogProductSimple/Price.php    |    2 +
 .../Fixture/CatalogProductSimple/TaxClass.php |    2 +
 .../CatalogProductSimple/TierPriceOptions.php |    2 +
 .../Test/Fixture/CatalogProductVirtual.php    |    3 +
 .../Test/Fixture/ConfigurableProduct.php      |    2 +
 .../Catalog/Test/Fixture/ProductAttribute.php |    2 +
 .../Handler/CatalogProductSimple/Curl.php     |    3 +
 .../Test/Handler/Curl/CreateProduct.php       |    2 +
 .../Test/Page/Category/CatalogCategory.php    |    2 +
 .../Page/Category/CatalogCategoryEdit.php     |    2 +
 .../Test/Repository/CatalogCategory.php       |    6 +
 .../Test/Repository/CatalogProductSimple.php  |    7 +
 .../Product/EditSimpleProductTest.php         |    1 -
 .../Fixture/CatalogSearchQuery/SearchData.php |    2 +
 .../TestCase/AdvancedSearchEntityTest.php     |    2 +
 .../Test/Handler/CmsPage/CmsPageInterface.php |    2 +-
 .../Fixture/CatalogProductConfigurable.php    |    6 +-
 .../AttributeOptions.php                      |    2 +
 .../ConfigurableOptions.php                   |    2 +
 .../CatalogProductConfigurable/Price.php      |    2 +
 .../Repository/CatalogProductConfigurable.php |    6 +
 .../Customer/Test/Block/Form/Login.php        |    2 +
 .../Test/Constraint/AssertCustomerInGrid.php  |    2 +
 .../Test/Fixture/AddressInjectable.php        |    2 +
 .../Fixture/CustomerGroup/TaxClassIds.php     |    2 +
 .../Test/Fixture/CustomerInjectable.php       |    2 +
 .../Test/Repository/CustomerInjectable.php    |    2 +
 .../Fixture/CatalogProductDownloadable.php    |    3 +
 .../CatalogProductDownloadable/Links.php      |    2 +
 .../CatalogProductDownloadable/Samples.php    |    2 +
 .../Magento/Review/Test/Repository/Rating.php |    2 +
 .../Sitemap/Test/Repository/Sitemap.php       |    6 +
 .../Test/Block/Adminhtml/Rule/Edit/Form.php   |    2 +
 .../Test/Constraint/AssertTaxRuleApplying.php |    2 +
 .../Tax/Test/Fixture/TaxRule/TaxClass.php     |    2 +
 .../Tax/Test/Fixture/TaxRule/TaxRate.php      |    2 +
 .../Tax/Test/Handler/Curl/RemoveTaxRule.php   |    2 +
 .../Tax/Test/Handler/TaxClass/Curl.php        |    6 +-
 .../Magento/Tax/Test/Handler/TaxRate/Curl.php |    6 +-
 .../Magento/Tax/Test/Handler/TaxRule/Curl.php |    2 +
 .../Magento/Tax/Test/Repository/TaxClass.php  |    6 +
 .../Magento/Tax/Test/Repository/TaxRate.php   |    8 +
 .../Magento/Tax/Test/Repository/TaxRule.php   |    6 +
 .../Test/TestCase/DeleteTaxRuleEntityTest.php |    2 +
 .../Test/TestCase/UpdateTaxRuleEntityTest.php |    2 +
 .../Test/Fixture/UrlRewrite/IdPath.php        |    2 +
 .../UrlRewrite/Test/Repository/UrlRewrite.php |    2 +
 .../Test/Repository/UrlRewriteCategory.php    |    2 +
 .../Test/Repository/UrlRewriteProduct.php     |    2 +
 .../User/Test/Constraint/LoginSuccess.php     |    2 +
 .../User/Test/Fixture/AdminUserInjectable.php |    1 +
 .../Test/Repository/AdminUserInjectable.php   |    2 +
 .../User/Test/Repository/AdminUserRole.php    |    2 +
 .../TestCase/DeleteAdminUserEntityTest.php    |    4 +-
 .../TestCase/DeleteUserRoleEntityTest.php     |    4 +-
 .../Mtf/TestSuite/InjectableTests.php         |    2 +
 .../Backend/Model/Search/CatalogTest.php      |   82 ++
 .../Magento/Catalog/Model/DesignTest.php      |    2 +-
 .../Model/Export}/ProductTest.php             |    8 +-
 .../Import}/Product/Type/AbstractTest.php     |    8 +-
 .../Model/Import}/ProductTest.php             |   18 +-
 .../_files/product_with_custom_options.csv    |    0
 .../Import}/_files/products_to_import.csv     |    0
 ...oducts_to_import_invalid_attribute_set.csv |    0
 .../products_to_import_with_datetime.csv      |    0
 .../Model/Resource/Theme/CollectionTest.php   |   18 +-
 .../Core/Model/Theme/CollectionTest.php       |    4 +-
 .../Core/Model/Theme/Domain/VirtualTest.php   |    6 +-
 .../Magento/Core/Model/ThemeTest.php          |    4 +-
 .../design/adminhtml/vendor_test/theme.xml    |    2 +-
 .../area_two/vendor_theme_one/theme.xml       |    2 +-
 .../design_area/vendor_theme_one/theme.xml    |    2 +-
 .../design/frontend/magento_default/theme.xml |    2 +-
 .../frontend/magento_default_iphone/theme.xml |    2 +-
 .../frontend/test_cache_test_theme/theme.xml  |    2 +-
 .../design/frontend/test_default/theme.xml    |    2 +-
 .../frontend/test_publication/theme.xml       |    2 +-
 .../design/frontend/test_test_theme/theme.xml |    2 +-
 .../frontend/vendor_custom_theme/theme.xml    |    2 +-
 .../design/frontend/vendor_default/theme.xml  |    2 +-
 .../Magento/Core/_files/etc/module.xml        |    2 +-
 .../Magento/Core/_files/layout_update.php     |    2 +-
 .../Magento/Customer/Model/SessionTest.php    |    4 -
 .../Service/V1/CustomerAccountServiceTest.php |    3 +-
 .../Model}/Export/AddressTest.php             |    6 +-
 .../Model}/Export/CustomerTest.php            |    6 +-
 .../Model}/Import/AddressTest.php             |    6 +-
 .../Model}/Import/CustomerCompositeTest.php   |    4 +-
 .../Model}/Import/CustomerTest.php            |    6 +-
 .../Import/_files/address_import_delete.csv   |    0
 .../Import/_files/address_import_update.csv   |    0
 .../_files/customer_composite_delete.csv      |    0
 .../_files/customer_composite_update.csv      |    0
 .../Import/_files/customers_to_import.csv     |    0
 .../design/frontend/vendor_test/theme.xml     |    2 +-
 .../frontend/vendor_test_child/theme.xml      |    2 +-
 .../_files/design_editor_active.php           |    2 +-
 .../design/adminhtml/test_default/theme.xml   |    2 +-
 .../design/frontend/test_default/theme.xml    |    2 +-
 .../App/Helper/AbstractHelperTest.php}        |    6 +-
 .../design/frontend/test_default/theme.xml    |    2 +-
 .../design/frontend/test_parent/theme.xml     |    2 +-
 .../Config/_files/Magento/Test/etc/module.xml |    2 +-
 .../View/Design/Theme/ValidatorTest.php       |    2 +-
 .../design/adminhtml/vendor_test/theme.xml    |    2 +-
 .../area_two/vendor_theme_one/theme.xml       |    2 +-
 .../design_area/vendor_theme_one/theme.xml    |    2 +-
 .../design/frontend/magento_default/theme.xml |    2 +-
 .../frontend/magento_default_iphone/theme.xml |    2 +-
 .../frontend/test_cache_test_theme/theme.xml  |    2 +-
 .../design/frontend/test_default/theme.xml    |    2 +-
 .../frontend/test_publication/theme.xml       |    2 +-
 .../design/frontend/test_test_theme/theme.xml |    2 +-
 .../frontend/vendor_custom_theme/theme.xml    |    2 +-
 .../design/frontend/vendor_default/theme.xml  |    2 +-
 .../frontend/vendor_custom_theme/theme.xml    |    2 +-
 .../frontend/vendor_custom_theme2/theme.xml   |    2 +-
 .../design/frontend/vendor_default/theme.xml  |    2 +-
 .../vendor_standalone_theme/theme.xml         |    2 +-
 .../Magento/ImportExport/Model/ExportTest.php |    6 +-
 .../Model/_files/Magento/Test/etc/module.xml  |    2 +-
 .../Magento/Paypal/Block/Bml/BannersTest.php  |   80 ++
 .../Paypal/Model/Express/CheckoutTest.php     |   99 ++
 .../Model/Calculation/Rate/ConverterTest.php  |  205 ++++
 .../testsuite/Magento/Tax/Model/ClassTest.php |    4 +
 .../Model/Sales/Total/Quote/SubtotalTest.php  |  289 +++++
 .../V1/Data/QuoteDetailsBuilderTest.php       |  171 +++
 .../Data/TaxDetails/AppliedTaxBuilderTest.php |  244 ++++
 .../V1/Data/TaxDetails/ItemBuilderTest.php    |  231 ++++
 .../Service/V1/Data/TaxDetailsBuilderTest.php |  161 +++
 .../Service/V1/Data/TaxRateBuilderTest.php    |  166 +++
 .../Service/V1/Data/TaxRuleBuilderTest.php    |  219 ++++
 .../Data/TaxRuleSearchResultsBuilderTest.php  |  285 +++++
 .../Service/V1/TaxCalculationServiceTest.php  | 1032 +++++++++++++++++
 .../Tax/Service/V1/TaxRateServiceTest.php     |  345 ++++++
 .../Tax/Service/V1/TaxRuleFixtureFactory.php  |  162 +++
 .../Tax/Service/V1/TaxRuleServiceTest.php     |  279 +++++
 .../Magento/Tax/_files/tax_classes.php        |    8 +-
 .../Magento/User/Model/RulesTest.php          |   58 +-
 .../Webapi/Model/Config/_files/webapi.php     |   32 +-
 .../_files/code/Magento/Test/etc/module.xml   |    2 +-
 .../design/adminhtml/magento_basic/theme.xml  |    2 +-
 .../mage/validation/test-validation.js        |   45 +
 .../TestFramework/Helper/Categories.php       |    2 +-
 .../Integrity/AbstractConfig.php              |    3 +
 dev/tests/static/phpunit.xml.dist             |    2 +
 .../Integrity/App/Language/ConfigTest.php     |  102 ++
 .../Integrity/App/Language/PackageTest.php    |  118 ++
 .../App/Language/_files/known_invalid.xml     |   31 +
 .../App/Language/_files/known_valid.xml       |   31 +
 .../Magento/Test/Integrity/ConfigTest.php     |   38 -
 .../Magento/Webapi/Model/ConfigTest.php       |    2 -
 .../Test/Integrity/PageType/FilesTest.php     |   55 -
 .../Magento/Test/Integrity/Xml/SchemaTest.php |   47 +-
 .../Framework/Module/ModuleXMLTest.php        |   52 +
 .../Test/Legacy/_files/obsolete_classes.php   |  146 ++-
 .../Test/Legacy/_files/obsolete_methods.php   |   34 +-
 .../Legacy/_files/obsolete_properties.php     |    5 +-
 .../Php/_files/phpcpd/blacklist/common.txt    |    2 +
 .../Php/_files/phpcs/blacklist/common.txt     |   18 +-
 .../Test/Php/_files/whitelist/common.txt      |    7 +-
 .../Magento/Backend/Helper/DataTest.php       |   25 +
 .../Pricing/Adjustment/CalculatorTest.php     |    9 +
 .../Backend/CustomlayoutupdateTest.php        |  155 +++
 .../Category/Attribute/Backend/SortbyTest.php |  287 ++++-
 .../Category/Attribute/Source/LayoutTest.php  |   69 ++
 .../Category/Attribute/Source/PageTest.php    |   98 ++
 .../Category/Attribute/Source/SortbyTest.php  |   68 ++
 .../Config/CatalogClone/Media/ImageTest.php   |  133 +++
 .../Model/Config/Source/CategoryTest.php      |   95 ++
 .../Model/Config/Source/GridPerPageTest.php   |   53 +
 .../Model/Config/Source/ListPerPageTest.php   |   54 +
 .../Model/Config/Source/ListSortTest.php      |   64 +
 .../Source/Product/Options/TypeTest.php       |   79 ++
 .../Magento/Catalog/Model/FactoryTest.php     |   81 ++
 .../Model/Indexer/Product/FlatTest.php        |   99 ++
 .../Model/Layer/Filter/DecimalTest.php        |   59 +
 .../Magento/Catalog/Model/Layer/StateTest.php |   74 ++
 .../Product/Attribute/Backend/UrlkeyTest.php  |   93 ++
 .../Product/Attribute/Frontend/ImageTest.php  |  122 ++
 .../Model/Product/Attribute/GroupTest.php     |   94 ++
 .../Catalog/Model/Product/ConditionTest.php   |  114 ++
 .../Helper/ProductLinksTest.php               |   95 ++
 .../Model/Product/Option/UrlBuilderTest.php   |   65 ++
 .../Model/Product/Option/ValueTest.php        |  304 +++++
 .../Model/Product/Type/AbstractTypeTest.php   |  132 ++-
 .../Catalog/Model/Product/TypeTest.php        |  306 ++++-
 .../Magento/Catalog/Model/ProductTest.php     |  178 +++
 .../Data/Eav/AttributeMetadataBuilderTest.php |   54 +-
 .../V1/Data/Eav/AttributeMetadataTest.php     |    6 +-
 .../V1/Product/Attribute/ReadServiceTest.php  |  255 ++++
 .../V1/Product/Attribute/WriteServiceTest.php |  293 +++++
 .../Product/AttributeSet/ReadServiceTest.php  |    5 +
 .../V1/ProductAttributeReadServiceTest.php    |   90 --
 .../V1/ProductAttributeServiceTest.php        |  176 +++
 .../Service/V1/ProductMetadataServiceTest.php |   11 +-
 .../Catalog/Service/V1/ProductServiceTest.php |    7 +-
 .../Model/Export}/ProductTest.php             |    4 +-
 .../Model/Export}/StubProduct.php             |    4 +-
 .../Model/Import/Product/Type}/OptionTest.php |  105 +-
 .../_files/product_with_custom_options.csv    |    0
 .../row_data_ambiguity_different_type.php     |    0
 .../row_data_ambiguity_several_db_rows.php    |    0
 .../_files/row_data_main_empty_title.php      |    0
 .../_files/row_data_main_incorrect_type.php   |    0
 .../row_data_main_invalid_max_characters.php  |    0
 .../_files/row_data_main_invalid_price.php    |    0
 .../row_data_main_invalid_sort_order.php      |    0
 .../_files/row_data_main_invalid_store.php    |    0
 ...row_data_main_max_characters_less_zero.php |    0
 .../Type}/_files/row_data_main_no_title.php   |    0
 .../row_data_main_sort_order_less_zero.php    |    0
 .../Type}/_files/row_data_main_valid.php      |    0
 .../_files/row_data_no_custom_option.php      |    0
 .../row_data_secondary_incorrect_price.php    |    0
 .../row_data_secondary_incorrect_row_sort.php |    0
 .../row_data_secondary_invalid_store.php      |    0
 .../row_data_secondary_row_sort_less_zero.php |    0
 .../Type}/_files/row_data_secondary_valid.php |    0
 .../Model/Import}/ProductTest.php             |   28 +-
 .../Product/Flat/Plugin/ImportTest.php        |    4 +-
 .../Product/Price/Plugin/ImportTest.php       |    6 +-
 .../CatalogSearch/Controller/AdvancedTest.php |   73 ++
 .../CatalogSearch/Model/AdvancedTest.php      |  163 +++
 .../Model/Export/RowCustomizerTest.php        |    4 +-
 .../Core/Model/Theme/ValidationTest.php       |    2 +-
 .../Magento/Customer/Helper/AddressTest.php   |  302 ++++-
 .../Magento/Customer/Helper/ViewTest.php      |  142 +++
 .../Model/Address/AbstractAddressTest.php     |  328 ++++++
 .../Customer/Model/Address/ConverterTest.php  |  297 +++++
 .../Magento/Customer/Model/AddressTest.php    |  152 +++
 .../Magento/Customer/Model/ConverterTest.php  |  150 ++-
 .../Attribute/Backend/BillingTest.php         |   93 ++
 .../Attribute/Backend/PasswordTest.php        |  101 ++
 .../Attribute/Backend/ShippingTest.php        |   94 ++
 .../Customer/Attribute/Backend/StoreTest.php  |   98 ++
 .../Attribute/Backend/WebsiteTest.php         |   92 ++
 .../Magento/Customer/Model/CustomerTest.php   |  191 ++-
 .../Group/Grid/ServiceCollectionTest.php      |    4 +-
 .../Magento/Customer/Model/SessionTest.php    |  113 +-
 .../Service/V1/CustomerAccountServiceTest.php |  559 ++++++---
 .../Service/V1/CustomerAddressServiceTest.php |    3 +-
 .../Model}/Export/AddressTest.php             |   18 +-
 .../Model}/Export/CustomerTest.php            |    4 +-
 .../Model}/Import/AbstractCustomerTest.php    |   16 +-
 .../Model}/Import/AddressTest.php             |   18 +-
 .../Model}/Import/CustomerCompositeTest.php   |   14 +-
 .../Model}/Import/CustomerTest.php            |    8 +-
 .../customer_composite_prepare_row_for_db.csv |    0
 .../_files/row_data_abstract_empty_email.php  |    0
 .../row_data_abstract_empty_website.php       |    0
 .../row_data_abstract_invalid_email.php       |    0
 .../row_data_abstract_invalid_website.php     |    0
 .../_files/row_data_abstract_no_email.php     |    0
 .../_files/row_data_abstract_no_website.php   |    0
 .../Import/_files/row_data_abstract_valid.php |    0
 ..._data_address_delete_address_not_found.php |    0
 ...w_data_address_delete_empty_address_id.php |    0
 .../row_data_address_delete_no_customer.php   |    0
 .../_files/row_data_address_delete_valid.php  |    0
 ...dress_update_absent_required_attribute.php |    0
 ...w_data_address_update_empty_address_id.php |    0
 ...row_data_address_update_invalid_region.php |    0
 .../row_data_address_update_no_customer.php   |    0
 .../_files/row_data_address_update_valid.php  |    0
 .../Resource}/Import/Customer/StorageTest.php |    2 +-
 .../Import/CustomerComposite/DataTest.php     |   14 +-
 .../Magento/Framework/App/AreaListTest.php    |   60 +-
 .../Framework/App/Config/ElementTest.php      |   42 +-
 .../Framework/App/Config/ValueTest.php        |  179 +++
 .../Framework/App/Config/_files/element.xml   |   46 +
 .../App/DefaultPath/DefaultPathTest.php       |   40 +-
 .../App/EntryPoint/EntryPointTest.php         |   92 +-
 .../Framework/App/Language/DictionaryTest.php |  156 +++
 .../App/Resource/ConnectionFactoryTest.php    |  199 ++++
 .../Framework/App/Route/ConfigTest.php        |   81 ++
 .../Magento/Framework/ArchiveTest.php         |   50 +-
 .../Magento/Framework/Config/ThemeTest.php    |    8 +-
 .../_files/area/default_default/theme.xml     |    2 +-
 .../Config/_files/area/default_test/theme.xml |    2 +-
 .../_files/area/default_test2/theme.xml       |    2 +-
 .../Config/_files/area/test_default/theme.xml |    2 +-
 .../theme.xml                                 |    2 +-
 .../Framework/Config/_files/theme_invalid.xml |    2 +-
 .../Magento/Framework/Convert/ExcelTest.php   |   29 +-
 .../Framework/Convert/_files/output.txt       |    1 -
 .../Framework/Convert/_files/sample.xml       |   89 ++
 .../Magento/Framework/File/CsvTest.php        |   80 ++
 .../Framework/Filter/ArrayFilterTest.php      |   62 +
 .../Filter/Input/MaliciousCodeTest.php        |  157 +++
 .../Magento/Framework/Filter/InputTest.php    |   74 ++
 .../Framework/Filter/Object/GridTest.php      |   96 ++
 .../Magento/Framework/Filter/SprintfTest.php  |   34 +
 .../Template/Tokenizer/ParameterTest.php      |   77 ++
 .../Template/Tokenizer/VariableTest.php}      |   45 +-
 .../Magento/Framework/Filter/TemplateTest.php |   78 ++
 .../Less/File/Collector/AggregatedTest.php    |  166 +++
 .../Less/File/Collector/LibraryTest.php       |  175 +++
 .../Magento/Framework/Locale/ConfigTest.php   |  224 ++++
 .../Magento/Framework/Locale/CurrencyTest.php |  215 ++++
 .../Locale/Hierarchy/Config/ConverterTest.php |   67 --
 .../Hierarchy/Config/FileResolverTest.php     |   99 --
 .../Framework/Locale/Hierarchy/ConfigTest.php |   88 --
 .../Model/Resource/Db/AbstractDbTest.php      |  389 +++++++
 .../Db/Collection/AbstractCollectionTest.php  |  437 +++++++
 .../Module/Declaration/Converter/DomTest.php  |    8 +-
 .../_files/converted_valid_module.php         |    4 +-
 .../Converter/_files/valid_module.xml         |    6 +-
 .../app/code/Module/Four/etc/module.xml       |    2 +-
 .../_files/app/code/Module/One/etc/module.xml |    4 +-
 .../app/code/Module/Three/etc/module.xml      |    4 +-
 .../_files/app/code/Module/Two/etc/module.xml |    4 +-
 .../_files/app/etc/custom/module.xml          |    2 +-
 .../Declaration/Reader/FilesystemTest.php     |    6 +-
 .../Magento/Framework/TranslateTest.php       |   26 +-
 .../Model/Export/Config/_files/export.php     |   24 +-
 .../Model/Export/Config/_files/export.xml     |    8 +-
 .../Config/_files/export_merged_valid.xml     |    4 +-
 .../Export/Config/_files/export_valid.xml     |    6 +-
 .../_files/invalidExportMergedXmlArray.php    |    9 +-
 .../Config/_files/invalidExportXmlArray.php   |   33 +-
 .../ImportExport/Model/Export/ConfigTest.php  |   43 +-
 .../Model/Import/Config/_files/import.php     |   54 +-
 .../Model/Import/Config/_files/import.xml     |   12 +-
 .../Config/_files/invalidImportXmlArray.php   |   35 +-
 .../Import/Config/_files/valid_import.xml     |    3 +-
 .../ImportExport/Model/Import/ConfigTest.php  |   43 +-
 .../Controller/Adminhtml/IntegrationTest.php  |   24 +-
 .../Integration/Helper/Oauth/ConsumerTest.php |    4 +-
 .../Integration/Helper/Oauth/RequestTest.php  |   22 +-
 .../Magento/Integration/Model/ManagerTest.php |    4 +-
 .../Magento/Integration/Oauth/OauthTest.php   |   41 +-
 .../IntegrationTest.php}                      |   12 +-
 .../{OauthV1Test.php => V1/OauthTest.php}     |   14 +-
 .../Magento/Paypal/Block/Bml/ShortcutTest.php |  145 +++
 .../Paypal/Block/Express/ReviewTest.php       |  111 +-
 .../Paypal/Block/Express/ShortcutTest.php     |   14 +-
 .../Magento/Paypal/Controller/ExpressTest.php |  355 ++++++
 .../Helper/Shortcut/CheckoutValidatorTest.php |  187 +++
 .../Paypal/Helper/Shortcut/FactoryTest.php    |   80 ++
 .../Paypal/Helper/Shortcut/ValidatorTest.php  |  170 +++
 .../Magento/Paypal/Model/Api/NvpTest.php      |  171 +++
 .../Model/Api/ProcessableExceptionTest.php    |   81 ++
 .../Magento/Paypal/Model/ConfigTest.php       |  207 +++-
 .../Magento/Paypal/Model/ExpressTest.php      |  139 +++
 .../Magento/Paypal/Model/ObserverTest.php     |   42 +-
 .../Paypal/Model/PayflowExpressTest.php       |    2 +
 .../Paypal/Model/PayflowadvancedTest.php      |  326 ------
 .../Magento/Paypal/Model/PayflowlinkTest.php  |  342 +-----
 .../Magento/Paypal/Model/PayflowproTest.php   |   35 +-
 .../Magento/Sales/Block/Order/HistoryTest.php |   10 +-
 .../Magento/Sales/Block/Order/RecentTest.php  |   10 +-
 .../Model/Calculation/Rate/ConverterTest.php  |  254 ++++
 .../Model/Calculation/RateRegistryTest.php    |  150 +++
 .../Model/Calculation/TaxRuleRegistryTest.php |  102 ++
 .../Tax/Service/V1/TaxRateServiceTest.php     |  295 +++++
 .../Tax/Service/V1/TaxRuleServiceTest.php     |  325 ++++++
 .../Response/PartialResponseProcessorTest.php |  271 +++++
 .../Webapi/Model/Config/_files/webapi.php     |   45 +-
 .../Webapi/Model/Config/_files/webapi.xml     |    9 +
 .../Model/Plugin/IntegrationServiceV1Test.php |    2 +-
 .../Magento/Webapi/Model/Plugin/SetupTest.php |    4 +-
 .../Magento/Webapi/Model/Soap/ConfigTest.php  |   12 +-
 .../Magento/Framework/App/Filesystem.php      |    2 +-
 .../App/Filesystem/DirectoryList.php          |    2 +-
 .../Framework/App/Language/Dictionary.php     |  258 +++++
 .../Framework/App/Language/package.xsd        |   51 +-
 .../Magento/Framework/AppInterface.php        |    2 +-
 .../Framework/Archive/Helper/File/Bz.php      |    8 +-
 .../Framework/Archive/Helper/File/Gz.php      |    8 +-
 .../Magento/Framework/Config/etc/theme.xsd    |    2 +-
 .../Magento/Framework/Convert/Excel.php       |    2 +-
 .../Framework/Filter/Input/MaliciousCode.php  |    6 +-
 .../Magento/Framework/Filter/Object/Grid.php  |    4 +-
 .../Locale/Hierarchy/Config/Converter.php     |   77 --
 .../Locale/Hierarchy/Config/FileResolver.php  |   66 --
 .../Locale/Hierarchy/Config/Reader.php        |   66 --
 .../Db/Collection/AbstractCollection.php      |    8 +-
 .../Module/Declaration/Converter/Dom.php      |    6 +-
 .../Magento/Framework/Module/Setup.php        |    4 +-
 .../Magento/Framework/Module/etc/module.xsd   |    6 +-
 .../Magento/Framework/Oauth/Exception.php     |   22 +-
 .../Framework/Oauth/Helper/Request.php        |   75 +-
 .../Magento/Framework/Oauth/Oauth.php         |   28 +-
 .../OauthInputException.php}                  |   22 +-
 .../V1/Data/AbstractSearchResultsBuilder.php  |  119 ++
 .../Service/V1/Data/SearchResults.php         |   14 +-
 lib/internal/Magento/Framework/Translate.php  |   83 +-
 .../Framework/View/Design/Theme/Validator.php |    2 +-
 lib/web/mage/adminhtml/form.js                |   19 +-
 lib/web/mage/validation.js                    |   90 +-
 783 files changed, 29318 insertions(+), 4472 deletions(-)
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php
 rename app/code/Magento/Catalog/Service/V1/Data/{ProductAttributeType.php => Eav/Product/Attribute/Type.php} (86%)
 rename app/code/Magento/Catalog/Service/V1/Data/{ProductAttributeTypeBuilder.php => Eav/Product/Attribute/TypeBuilder.php} (77%)
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResultsBuilder.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Product/SearchResults.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Data/Product/SearchResultsBuilder.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadService.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteService.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php
 delete mode 100644 app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php
 create mode 100644 app/code/Magento/Catalog/Service/V1/ProductAttributeService.php
 rename app/code/Magento/Catalog/Service/V1/{ProductAttributeReadServiceInterface.php => ProductAttributeServiceInterface.php} (70%)
 rename app/code/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/Product.php (98%)
 rename app/code/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/Product/Type/AbstractType.php (97%)
 rename app/code/Magento/{ConfigurableProduct/Model/Export/Entity => CatalogImportExport/Model/Export}/Product/Type/Configurable.php (84%)
 rename app/code/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/Product/Type/Factory.php (92%)
 rename app/code/Magento/{GroupedProduct/Model/Export/Entity => CatalogImportExport/Model/Export}/Product/Type/Grouped.php (87%)
 rename app/code/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/Product/Type/Simple.php (93%)
 rename app/code/Magento/{ConfigurableProduct => CatalogImportExport}/Model/Export/RowCustomizer.php (97%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/Model/Export/RowCustomizer/Composite.php (95%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/Model/Export/RowCustomizerInterface.php (97%)
 rename app/code/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product.php (97%)
 rename app/code/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Option.php (99%)
 rename app/code/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/AbstractType.php (94%)
 rename app/code/Magento/{ConfigurableProduct/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/Configurable.php (97%)
 rename app/code/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/Factory.php (93%)
 rename app/code/Magento/{GroupedProduct/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/Grouped.php (93%)
 rename app/code/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/Simple.php (91%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/Model/Import/Proxy/Product.php (95%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/Model/Import/Proxy/Product/Resource.php (95%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/Model/Import/Uploader.php (99%)
 rename app/code/Magento/{Catalog => CatalogImportExport}/Model/Indexer/Product/Flat/Plugin/Import.php (96%)
 rename app/code/Magento/{Catalog => CatalogImportExport}/Model/Indexer/Product/Price/Plugin/Import.php (88%)
 rename app/code/Magento/{GroupedProduct/etc/export.xml => CatalogImportExport/etc/config.xml} (85%)
 create mode 100644 app/code/Magento/CatalogImportExport/etc/di.xml
 rename app/code/Magento/{ImportExport => CatalogImportExport}/etc/export.xml (66%)
 rename app/code/Magento/{ImportExport => CatalogImportExport}/etc/import.xml (59%)
 create mode 100644 app/code/Magento/CatalogImportExport/etc/module.xml
 create mode 100644 app/code/Magento/CatalogSearch/Model/Layer/Advanced.php
 create mode 100644 app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php
 create mode 100644 app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php
 create mode 100644 app/code/Magento/CatalogSearch/Model/Layer/Advanced/FilterableAttributeList.php
 create mode 100644 app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php
 create mode 100644 app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/Address.php (97%)
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/Customer.php (99%)
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/AbstractCustomer.php (95%)
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/Address.php (98%)
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/Customer.php (98%)
 rename app/code/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/CustomerComposite.php (95%)
 rename app/code/Magento/{Customer/Model/Resource/ImportExport => CustomerImportExport/Model/Resource}/Import/Customer/Storage.php (98%)
 rename app/code/Magento/{Customer/Model/Resource/ImportExport => CustomerImportExport/Model/Resource}/Import/CustomerComposite/Data.php (96%)
 rename app/code/Magento/{ConfigurableProduct/etc/export.xml => CustomerImportExport/etc/adminhtml/routes.xml} (77%)
 rename app/code/Magento/{ConfigurableProduct/etc/import.xml => CustomerImportExport/etc/config.xml} (79%)
 rename app/code/Magento/{Customer => CustomerImportExport}/etc/export.xml (86%)
 rename app/code/Magento/{Customer => CustomerImportExport}/etc/import.xml (76%)
 create mode 100644 app/code/Magento/CustomerImportExport/etc/module.xml
 rename app/code/Magento/{Customer/view/adminhtml/layout/customer_index_exportcsv.xml => CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportcsv.xml} (100%)
 rename app/code/Magento/{Customer/view/adminhtml/layout/customer_index_exportxml.xml => CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml} (100%)
 create mode 100644 app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml
 create mode 100644 app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php
 rename app/code/Magento/Integration/Service/{IntegrationV1.php => V1/Integration.php} (96%)
 rename app/code/Magento/Integration/Service/{IntegrationV1Interface.php => V1/IntegrationInterface.php} (96%)
 rename app/code/Magento/Integration/Service/{OauthV1.php => V1/Oauth.php} (95%)
 rename app/code/Magento/Integration/Service/{OauthV1Interface.php => V1/OauthInterface.php} (98%)
 create mode 100644 app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml
 create mode 100644 app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php
 create mode 100644 app/code/Magento/Paypal/Block/Bml/Banners.php
 create mode 100644 app/code/Magento/Paypal/Block/Bml/Form.php
 create mode 100644 app/code/Magento/Paypal/Block/Bml/Shortcut.php
 create mode 100644 app/code/Magento/Paypal/Block/Payflow/Bml/Form.php
 create mode 100644 app/code/Magento/Paypal/Controller/Bml.php
 create mode 100644 app/code/Magento/Paypal/Controller/Payflowbml.php
 create mode 100644 app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php
 create mode 100644 app/code/Magento/Paypal/Helper/Shortcut/Factory.php
 create mode 100644 app/code/Magento/Paypal/Helper/Shortcut/Validator.php
 create mode 100644 app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php
 create mode 100644 app/code/Magento/Paypal/Model/Api/ProcessableException.php
 create mode 100644 app/code/Magento/Paypal/Model/Bml.php
 rename app/code/Magento/Paypal/{Block/PayflowExpress/Shortcut.php => Model/Payflow/Bml.php} (63%)
 create mode 100644 app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php
 create mode 100644 app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php
 create mode 100644 app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml
 create mode 100644 app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml
 create mode 100644 app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml
 create mode 100644 app/code/Magento/Paypal/view/frontend/templates/bml.phtml
 delete mode 100644 app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml
 delete mode 100644 app/code/Magento/Paypal/view/frontend/templates/payflowexpress/review.phtml
 create mode 100644 app/code/Magento/Tax/Model/Calculation/Rate/Converter.php
 create mode 100644 app/code/Magento/Tax/Model/Calculation/RateRegistry.php
 create mode 100644 app/code/Magento/Tax/Model/Calculation/TaxRuleConverter.php
 create mode 100644 app/code/Magento/Tax/Model/Calculation/TaxRuleRegistry.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetails.php
 rename lib/internal/Magento/Framework/Locale/Hierarchy/Config/SchemaLocator.php => app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTax.php (53%)
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRate.php
 rename app/code/Magento/{Catalog/Service/V1/Data/SearchResultsBuilder.php => Tax/Service/V1/Data/TaxDetails/AppliedTaxRateBuilder.php} (57%)
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxDetailsBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRate.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRateBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRule.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResults.php
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilder.php
 rename dev/tests/unit/testsuite/Magento/Paypal/Block/PayflowExpress/ShortcutTest.php => app/code/Magento/Tax/Service/V1/Data/ZipRange.php (63%)
 create mode 100644 app/code/Magento/Tax/Service/V1/Data/ZipRangeBuilder.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxCalculationService.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxRateService.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxRateServiceInterface.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxRuleService.php
 create mode 100644 app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
 create mode 100644 app/code/Magento/Webapi/Controller/Login.php
 create mode 100644 app/code/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessor.php
 rename app/code/Magento/{GroupedProduct/etc/import.xml => Webapi/etc/frontend/routes.xml} (80%)
 rename dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/custom/hierarchy_config.xml => app/i18n/Magento/de_DE/language.xml (80%)
 rename dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/default/hierarchy_config.xml => app/i18n/Magento/en_US/language.xml (80%)
 create mode 100644 app/i18n/Magento/es_ES/language.xml
 create mode 100644 app/i18n/Magento/fr_FR/language.xml
 create mode 100644 app/i18n/Magento/nl_NL/language.xml
 create mode 100644 app/i18n/Magento/pt_BR/language.xml
 create mode 100644 app/i18n/Magento/zh_CN/language.xml
 create mode 100644 dev/tests/integration/testsuite/Magento/Backend/Model/Search/CatalogTest.php
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/ProductTest.php (94%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/Product/Type/AbstractTest.php (96%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/ProductTest.php (97%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/_files/product_with_custom_options.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/_files/products_to_import.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/_files/products_to_import_invalid_attribute_set.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/_files/products_to_import_with_datetime.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/AddressTest.php (97%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/CustomerTest.php (97%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/AddressTest.php (99%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/CustomerCompositeTest.php (98%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/CustomerTest.php (97%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/address_import_delete.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/address_import_update.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/customer_composite_delete.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/customer_composite_update.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/customers_to_import.csv (100%)
 rename dev/tests/integration/testsuite/Magento/{Core/Helper/AbstractTest.php => Framework/App/Helper/AbstractHelperTest.php} (92%)
 create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Block/Bml/BannersTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetailsBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRateBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilderTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleFixtureFactory.php
 create mode 100644 dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
 create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
 create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
 create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
 create mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
 delete mode 100644 dev/tests/static/testsuite/Magento/Test/Integrity/PageType/FilesTest.php
 create mode 100644 dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/Module/ModuleXMLTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Attribute/Backend/CustomlayoutupdateTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/LayoutTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/PageTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/SortbyTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/CatalogClone/Media/ImageTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/CategoryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/GridPerPageTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListPerPageTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListSortTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/Product/Options/TypeTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/FactoryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/FlatTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/Filter/DecimalTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/StateTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/UrlkeyTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Frontend/ImageTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/GroupTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/UrlBuilderTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/ValueTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeReadServiceTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeServiceTest.php
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/ProductTest.php (92%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Export/Entity => CatalogImportExport/Model/Export}/StubProduct.php (91%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/OptionTest.php (90%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/product_with_custom_options.csv (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_ambiguity_different_type.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_ambiguity_several_db_rows.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_empty_title.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_incorrect_type.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_invalid_max_characters.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_invalid_price.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_invalid_sort_order.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_invalid_store.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_max_characters_less_zero.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_no_title.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_sort_order_less_zero.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_main_valid.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_no_custom_option.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_secondary_incorrect_price.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_secondary_incorrect_row_sort.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_secondary_invalid_store.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_secondary_row_sort_less_zero.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity/Product => CatalogImportExport/Model/Import/Product/Type}/_files/row_data_secondary_valid.php (100%)
 rename dev/tests/unit/testsuite/Magento/{ImportExport/Model/Import/Entity => CatalogImportExport/Model/Import}/ProductTest.php (90%)
 rename dev/tests/unit/testsuite/Magento/{Catalog => CatalogImportExport}/Model/Indexer/Product/Flat/Plugin/ImportTest.php (90%)
 rename dev/tests/unit/testsuite/Magento/{Catalog => CatalogImportExport}/Model/Indexer/Product/Price/Plugin/ImportTest.php (89%)
 create mode 100644 dev/tests/unit/testsuite/Magento/CatalogSearch/Controller/AdvancedTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Helper/ViewTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Address/AbstractAddressTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Address/ConverterTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/AddressTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/PasswordTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/StoreTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/WebsiteTest.php
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/AddressTest.php (92%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Export/CustomerTest.php (98%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/AbstractCustomerTest.php (92%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/AddressTest.php (97%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/CustomerCompositeTest.php (98%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/CustomerTest.php (96%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/customer_composite_prepare_row_for_db.csv (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_empty_email.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_empty_website.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_invalid_email.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_invalid_website.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_no_email.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_no_website.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_abstract_valid.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_delete_address_not_found.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_delete_empty_address_id.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_delete_no_customer.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_delete_valid.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_update_absent_required_attribute.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_update_empty_address_id.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_update_invalid_region.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_update_no_customer.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/ImportExport => CustomerImportExport/Model}/Import/_files/row_data_address_update_valid.php (100%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/Resource/ImportExport => CustomerImportExport/Model/Resource}/Import/Customer/StorageTest.php (98%)
 rename dev/tests/unit/testsuite/Magento/{Customer/Model/Resource/ImportExport => CustomerImportExport/Model/Resource}/Import/CustomerComposite/DataTest.php (93%)
 rename dev/tests/{integration => unit}/testsuite/Magento/Framework/App/Config/ElementTest.php (60%)
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/App/Config/ValueTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/App/Config/_files/element.xml
 rename lib/internal/Magento/Framework/Locale/Hierarchy/Config.php => dev/tests/unit/testsuite/Magento/Framework/App/DefaultPath/DefaultPathTest.php (57%)
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/App/Resource/ConnectionFactoryTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Framework/Convert/_files/output.txt
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Convert/_files/sample.xml
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/ArrayFilterTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/Input/MaliciousCodeTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/InputTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/Object/GridTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/SprintfTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/ParameterTest.php
 rename dev/tests/{static/testsuite/Magento/Test/Integrity/Layout/FilesTest.php => unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/VariableTest.php} (50%)
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Filter/TemplateTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/AggregatedTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/LibraryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Locale/ConfigTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Locale/CurrencyTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/ConverterTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/FileResolverTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/ConfigTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/AbstractDbTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php
 rename dev/tests/unit/testsuite/Magento/Integration/Service/{IntegrationV1Test.php => V1/IntegrationTest.php} (98%)
 rename dev/tests/unit/testsuite/Magento/Integration/Service/{OauthV1Test.php => V1/OauthTest.php} (97%)
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Block/Bml/ShortcutTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Controller/ExpressTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/CheckoutValidatorTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/FactoryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Model/Api/ProcessableExceptionTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Model/ExpressTest.php
 delete mode 100644 dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowadvancedTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RateRegistryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TaxRuleRegistryTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
 create mode 100644 dev/tests/unit/testsuite/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessorTest.php
 create mode 100644 lib/internal/Magento/Framework/App/Language/Dictionary.php
 rename app/code/Magento/Core/etc/locale.xsd => lib/internal/Magento/Framework/App/Language/package.xsd (51%)
 delete mode 100644 lib/internal/Magento/Framework/Locale/Hierarchy/Config/Converter.php
 delete mode 100644 lib/internal/Magento/Framework/Locale/Hierarchy/Config/FileResolver.php
 delete mode 100644 lib/internal/Magento/Framework/Locale/Hierarchy/Config/Reader.php
 rename lib/internal/Magento/Framework/{Filter/GridArray/Grid.php => Oauth/OauthInputException.php} (72%)
 create mode 100644 lib/internal/Magento/Framework/Service/V1/Data/AbstractSearchResultsBuilder.php
 rename {app/code/Magento/Catalog => lib/internal/Magento/Framework}/Service/V1/Data/SearchResults.php (77%)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74d8042f568..bd296367839 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,81 @@
+2.0.0.0-dev84
+=============
+* Fixed bugs:
+  * Fixed an issue where an invalidly filled option did not become in focus after saving attempt on the Create New Order page in the backend
+  * Fixed an issue with the default configuration not being applied properly in the CAPTCHA configuration section
+  * Fixed an issue with optional State/Province fields on the Create New Order page being marked as required
+  * Fixed an issue with incorrect Customer model usage on session in community modules
+  * Fixed an issue where cache was not invalidated after applying catalog price rule
+  * Fixed an issue where an admin with custom permissions could not create Shopping Cart Price Rule/Catalog Price Rule
+  * Fixed an issue with REST request and response format being inconsistent
+  * Fixed an issue where there was an error on a bundle product page if bundle items contained an out of stock product
+  * Fixed a JS issue which appeared when adding associated products for a grouped product
+  * Fixed an issue where layered navigation was absent on the Advanced Search results page
+  * Fixed an issue where the leading "0" in numbers were truncated when exporting using Excel XML
+  * Fixed the price type attribute filter in Layered Navigation
+  * Fixed an issue with a fatal error in \Magento\Framework\ArchiveTest when bz2 extension was not installed
+  * Fixed an issue where an admin could search product by attributes set on the Store View level (except default store view)
+  * Fixed an issue where extra spaces in search values were not ignored during search and thus wrong search results were given
+* GitHub requests:
+  * [#542]  Fix ImportExport bug which occurs while importing multiple rows per entity
+  * [#544]  Performance tests not working
+* Framework improvements:
+  * Covered the following Magento application components with unit tests:
+      * `Customer/Model/Address.php`
+      * `Customer/Model/Address/AbstractAddress.php `
+      * `Customer/Model/Address/Converter.php`
+      * `Customer/Model/Customer.php`
+      * `Customer/Model/Customer/Attribute/Backend/Billing.php`
+      * `Customer/Model/Customer/Attribute/Backend/Shipping.php`
+      * `Customer/Model/Customer/Attribute/Backend/Store.php `
+      * `Customer/Model/Customer/Attribute/Backend/Website.php `
+      * `Customer/Model/Customer/Attribute/Backend/PasswordTest.php`
+      * `Customer/Helper/Address.php`
+      * `Customer/Helper/View.php`
+      * `Customer/Service/V1/CustomerAccountService.php`
+  * Covered Magento lib with unit tests:
+      * `lib/internal/Magento/Framework/Filter/*`
+      * `lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php`
+      * `lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php`
+      * `lib/internal/Magento/Framework/File/Uploader.php`
+      * `lib/internal/Magento/Framework/File/Csv.php`
+      * `lib/internal/Magento/Framework/Less/File/Collector/Aggregated.php`
+      * `lib/internal/Magento/Framework/Less/File/Collector/Library.php`
+      * `lib/internal/Magento/Framework/Locale/Config.php`
+      * `lib/internal/Magento/Framework/Locale/Currency.php`
+      * `lib/internal/Magento/Framework/App/Config/Element.php`
+      * `lib/internal/Magento/Framework/App/Config/Value.php`
+      * `lib/internal/Magento/Framework/App/DefaultPath/DefaultPath.php`
+      * `lib/internal/Magento/Framework/App/EntryPoint/EntryPoint.php`
+      * `lib/internal/Magento/Framework/App/Helper/AbstractHelper.php`
+      * `lib/internal/Magento/Framework/App/Resource/ConnectionFactory.php`
+      * `lib/internal/Magento/Framework/App/Route/Config.php`
+  * Implemented the ability for a mobile client to get a partial response
+  * Added authentication support for mobile
+  * Refactored the Oauth lib exception not to reference module classes
+  * Moved the authorization services according to the new directory format: was \Magento\Authz\Service\AuthorizationV1Interface, became \Magento\Authz\Service\V1\AuthorizationInterface
+  * Moved the integration services according to the new directory format:
+    * Was \Magento\Integration\Service\IntegrationV1, became \Magento\Integration\Service\V1\Integration
+    * Was \Magento\Integration\Service\OauthV1, became \Magento\Integration\Service\V1\Oauth
+  * Improved security of the integration registration
+  * Introduced language packages with ability to inherit dictionaries
+* Improved modularity of ImportExport
+* Created Service API for Magento_Catalog module:
+   * Implemented Product Attribute Media API
+   * Implemented Product Group Price API
+   * Implemented Product Attribute Write API
+   * Implemented Product Attribute Options Read and Write API
+* Created Service for the Magento Tax module:
+  * Implemented Tax Rule Service
+  * Implemented Tax Rate Service
+  * Implemented Tax Calculation Data Objects
+  * Implemented Tax Calculation Builders
+  * Implemented Tax Calculation Service
+* Covered the part of the Catalog Module with unit tests
+* Added PayPall Bill Me Later button
+* Streamlined checkout experience
+* Improved order review page for PayPal Express Checkout
+
 2.0.0.0-dev83
 =============
 * Created the Service API for the Magento_Catalog Module:
@@ -221,7 +299,7 @@
   * Fixed price inconsistencies between catalog and shopping cart
   * Added support for maintaining consistent price including tax for customers with different tax rates
   * Added support for applying tax rules with different priorities to subtotal only
-  
+
 * Fixed bugs:
   * Removed the extra '%' sign in the error\notice message on Gift Card Accounts page on the backend
   * Fixed an issue with image uploading functionality in the Catalog configuration
diff --git a/app/code/Magento/AdminNotification/etc/module.xml b/app/code/Magento/AdminNotification/etc/module.xml
index 2c770837bb5..e767d17381c 100644
--- a/app/code/Magento/AdminNotification/etc/module.xml
+++ b/app/code/Magento/AdminNotification/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_AdminNotification" version="2.0.0.0" active="true">
+    <module name="Magento_AdminNotification" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Authorizenet/etc/module.xml b/app/code/Magento/Authorizenet/etc/module.xml
index 715f39adf75..4b5c4d3a0a3 100644
--- a/app/code/Magento/Authorizenet/etc/module.xml
+++ b/app/code/Magento/Authorizenet/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Authorizenet" version="1.5.0.0" active="true">
+    <module name="Magento_Authorizenet" schema_version="1.5.0.0" active="true">
         <sequence>
             <module name="Magento_Sales"/>
             <module name="Magento_Checkout"/>
diff --git a/app/code/Magento/Authz/Service/AuthorizationV1.php b/app/code/Magento/Authz/Service/AuthorizationV1.php
index 54e3214e360..f8844e9bcf0 100644
--- a/app/code/Magento/Authz/Service/AuthorizationV1.php
+++ b/app/code/Magento/Authz/Service/AuthorizationV1.php
@@ -23,18 +23,18 @@
  */
 namespace Magento\Authz\Service;
 
-use Magento\Framework\Acl\Builder as AclBuilder;
-use Magento\Framework\Acl;
 use Magento\Authz\Model\UserIdentifier;
+use Magento\Framework\Acl;
+use Magento\Framework\Acl\Builder as AclBuilder;
+use Magento\Framework\Acl\RootResource as RootAclResource;
 use Magento\Framework\Logger;
-use Magento\Webapi\ServiceException as ServiceException;
-use Magento\Webapi\ServiceResourceNotFoundException;
 use Magento\User\Model\Resource\Role\CollectionFactory as RoleCollectionFactory;
 use Magento\User\Model\Resource\Rules\CollectionFactory as RulesCollectionFactory;
 use Magento\User\Model\Role;
 use Magento\User\Model\RoleFactory;
 use Magento\User\Model\RulesFactory;
-use Magento\Framework\Acl\RootResource as RootAclResource;
+use Magento\Webapi\ServiceException as ServiceException;
+use Magento\Webapi\ServiceResourceNotFoundException;
 
 /**
  * Authorization service.
@@ -44,6 +44,9 @@ use Magento\Framework\Acl\RootResource as RootAclResource;
  */
 class AuthorizationV1 implements AuthorizationV1Interface
 {
+    const PERMISSION_ANONYMOUS = 'anonymous';
+    const PERMISSION_SELF = 'self';
+
     /**
      * @var AclBuilder
      */
@@ -121,29 +124,12 @@ class AuthorizationV1 implements AuthorizationV1Interface
      */
     public function isAllowed($resources, UserIdentifier $userIdentifier = null)
     {
-        $resources = is_array($resources) ? $resources : array($resources);
+        $resources = is_array($resources) ? $resources : [$resources];
         $userIdentifier = $userIdentifier ? $userIdentifier : $this->_userIdentifier;
-        try {
-            $role = $this->_getUserRole($userIdentifier);
-            if (!$role) {
-                throw new ServiceResourceNotFoundException(
-                    __(
-                        'Role for user with ID "%1" and user type "%2" cannot be found.',
-                        $userIdentifier->getUserId(),
-                        $userIdentifier->getUserType()
-                    )
-                );
-            }
-            foreach ($resources as $resource) {
-                if (!$this->_aclBuilder->getAcl()->isAllowed($role->getId(), $resource)) {
-                    return false;
-                }
-            }
+        if ($this->_isAnonymousOrSelfAllowed($resources, $userIdentifier)) {
             return true;
-        } catch (\Exception $e) {
-            $this->_logger->logException($e);
-            return false;
         }
+        return $this->_isUserWithRoleAllowed($resources, $userIdentifier);
     }
 
     /**
@@ -180,7 +166,12 @@ class AuthorizationV1 implements AuthorizationV1Interface
      */
     public function getAllowedResources(UserIdentifier $userIdentifier)
     {
-        $allowedResources = array();
+        if ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_GUEST) {
+            return [self::PERMISSION_ANONYMOUS];
+        } elseif ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_CUSTOMER) {
+            return [self::PERMISSION_SELF];
+        }
+        $allowedResources = [];
         try {
             $role = $this->_getUserRole($userIdentifier);
             if (!$role) {
@@ -234,6 +225,9 @@ class AuthorizationV1 implements AuthorizationV1Interface
     protected function _createRole($userIdentifier)
     {
         $userType = $userIdentifier->getUserType();
+        if (!$this->_canRoleBeCreatedForUserType($userType)) {
+            throw new \LogicException("The role with user type '{$userType}' cannot be created");
+        }
         $userId = $userIdentifier->getUserId();
         switch ($userType) {
             case UserIdentifier::USER_TYPE_INTEGRATION:
@@ -246,17 +240,12 @@ class AuthorizationV1 implements AuthorizationV1Interface
                 throw new \LogicException("Unknown user type: '{$userType}'.");
         }
         $role = $this->_roleFactory->create();
-        $role->setRoleName(
-            $roleName
-        )->setUserType(
-            $userType
-        )->setUserId(
-            $userId
-        )->setRoleType(
-            $roleType
-        )->setParentId(
-            $parentId
-        )->save();
+        $role->setRoleName($roleName)
+            ->setUserType($userType)
+            ->setUserId($userId)
+            ->setRoleType($roleType)
+            ->setParentId($parentId)
+            ->save();
         return $role;
     }
 
@@ -270,6 +259,9 @@ class AuthorizationV1 implements AuthorizationV1Interface
     protected function _deleteRole($userIdentifier)
     {
         $userType = $userIdentifier->getUserType();
+        if (!$this->_canRoleBeCreatedForUserType($userType)) {
+            throw new \LogicException("The role with user type '{$userType}' cannot be created or deleted.");
+        }
         $userId = $userIdentifier->getUserId();
         switch ($userType) {
             case UserIdentifier::USER_TYPE_INTEGRATION:
@@ -287,13 +279,19 @@ class AuthorizationV1 implements AuthorizationV1Interface
      *
      * @param UserIdentifier $userIdentifier
      * @return Role|false Return false in case when no role associated with provided user was found.
+     * @throws \LogicException
      */
     protected function _getUserRole($userIdentifier)
     {
+        if (!$this->_canRoleBeCreatedForUserType($userIdentifier)) {
+            throw new \LogicException(
+                "The role with user type '{$userIdentifier->getUserType()}' does not exist and cannot be created"
+            );
+        }
         $roleCollection = $this->_roleCollectionFactory->create();
         $userType = $userIdentifier->getUserType();
-        $userId = $userIdentifier->getUserId();
         /** @var Role $role */
+        $userId = $userIdentifier->getUserId();
         $role = $roleCollection->setUserFilter($userId, $userType)->getFirstItem();
         return $role->getId() ? $role : false;
     }
@@ -304,6 +302,7 @@ class AuthorizationV1 implements AuthorizationV1Interface
      * @param Role $role
      * @param string[] $resources
      * @return void
+     * @throws \LogicException
      */
     protected function _associateResourcesWithRole($role, array $resources)
     {
@@ -311,4 +310,70 @@ class AuthorizationV1 implements AuthorizationV1Interface
         $rules = $this->_rulesFactory->create();
         $rules->setRoleId($role->getId())->setResources($resources)->saveRel();
     }
+
+    /**
+     * Check if there role can be associated with user having provided user type.
+     *
+     * Roles cannot be created for guests and customers.
+     *
+     * @param string $userType
+     * @return bool
+     */
+    protected function _canRoleBeCreatedForUserType($userType)
+    {
+        return ($userType != UserIdentifier::USER_TYPE_CUSTOMER) && ($userType != UserIdentifier::USER_TYPE_GUEST);
+    }
+
+    /**
+     * Check if the user has permission to access the requested resources.
+     *
+     * @param string[] $resources
+     * @param UserIdentifier $userIdentifier
+     * @return bool
+     */
+    protected function _isAnonymousOrSelfAllowed($resources, UserIdentifier $userIdentifier)
+    {
+        if (count($resources) == 1) {
+            $resource = reset($resources);
+            $isAnonymousAccess = ($resource == self::PERMISSION_ANONYMOUS);
+            $isSelfAccess = ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_CUSTOMER)
+                && ($resource == self::PERMISSION_SELF);
+            if ($isAnonymousAccess || $isSelfAccess) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if user who has role is allowed to access requested resources.
+     *
+     * @param string[] $resources
+     * @param UserIdentifier $userIdentifier
+     * @return bool
+     */
+    protected function _isUserWithRoleAllowed($resources, UserIdentifier $userIdentifier)
+    {
+        try {
+            $role = $this->_getUserRole($userIdentifier);
+            if (!$role) {
+                throw new ServiceResourceNotFoundException(
+                    __(
+                        'Role for user with ID "%1" and user type "%2" cannot be found.',
+                        $userIdentifier->getUserId(),
+                        $userIdentifier->getUserType()
+                    )
+                );
+            }
+            foreach ($resources as $resource) {
+                if (!$this->_aclBuilder->getAcl()->isAllowed($role->getId(), $resource)) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (\Exception $e) {
+            $this->_logger->logException($e);
+            return false;
+        }
+    }
 }
diff --git a/app/code/Magento/Authz/etc/module.xml b/app/code/Magento/Authz/etc/module.xml
index ff58965b959..4079bb85393 100644
--- a/app/code/Magento/Authz/etc/module.xml
+++ b/app/code/Magento/Authz/etc/module.xml
@@ -24,7 +24,10 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Authz" version="1.0.0.0" active="true">
+    <module name="Magento_Authz" schema_version="1.0.0.0" active="true">
+        <sequence>
+            <module name="Magento_User"/>
+        </sequence>
         <depends>
             <!--TODO: Dependency on Magento_User is temporary and should be eliminated when ACL is made global-->
             <module name="Magento_User"/>
diff --git a/app/code/Magento/Backend/Block/Widget/Grid.php b/app/code/Magento/Backend/Block/Widget/Grid.php
index 92ab24922cf..3cade6d445f 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid.php
@@ -397,17 +397,6 @@ class Grid extends \Magento\Backend\Block\Widget
         return $this;
     }
 
-    /**
-     * Decode URL encoded filter value recursive callback method
-     *
-     * @param string &$value
-     * @return void
-     */
-    protected function _decodeFilter(&$value)
-    {
-        $value = $this->_backendHelper->decodeFilter($value);
-    }
-
     /**
      * Apply pagination to collection
      *
diff --git a/app/code/Magento/Backend/Helper/Data.php b/app/code/Magento/Backend/Helper/Data.php
index 2b5abe6a3c7..d72ed1653b2 100644
--- a/app/code/Magento/Backend/Helper/Data.php
+++ b/app/code/Magento/Backend/Helper/Data.php
@@ -177,21 +177,22 @@ class Data extends AbstractHelper
         $data = array();
         $filterString = base64_decode($filterString);
         parse_str($filterString, $data);
-        array_walk_recursive($data, array($this, 'decodeFilter'));
+        array_walk_recursive(
+            $data,
+            // @codingStandardsIgnoreStart
+            /**
+             * Decodes URL-encoded string and trims whitespaces from the beginning and end of a string
+             *
+             * @param string $value
+             */
+            // @codingStandardsIgnoreEnd
+            function (&$value) {
+                $value = trim(rawurldecode($value));
+            }
+        );
         return $data;
     }
 
-    /**
-     * Decode URL encoded filter value recursive callback method
-     *
-     * @param string &$value
-     * @return void
-     */
-    public function decodeFilter(&$value)
-    {
-        $value = rawurldecode($value);
-    }
-
     /**
      * Generate unique token for reset password confirmation link
      *
diff --git a/app/code/Magento/Backend/Model/Search/Catalog.php b/app/code/Magento/Backend/Model/Search/Catalog.php
index 005eeaf01d4..2a63c068e96 100644
--- a/app/code/Magento/Backend/Model/Search/Catalog.php
+++ b/app/code/Magento/Backend/Model/Search/Catalog.php
@@ -81,7 +81,7 @@ class Catalog extends \Magento\Framework\Object
             'name'
         )->addAttributeToSelect(
             'description'
-        )->addSearchFilter(
+        )->addBackendSearchFilter(
             $this->getQuery()
         )->setCurPage(
             $this->getStart()
diff --git a/app/code/Magento/Backend/etc/module.xml b/app/code/Magento/Backend/etc/module.xml
index 7a699759495..101b83e0776 100644
--- a/app/code/Magento/Backend/etc/module.xml
+++ b/app/code/Magento/Backend/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Backend" version="2.0.0.0" active="true">
+    <module name="Magento_Backend" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Directory"/>
         </sequence>
diff --git a/app/code/Magento/Backup/etc/module.xml b/app/code/Magento/Backup/etc/module.xml
index 9009e6191b1..20db9e5b28c 100644
--- a/app/code/Magento/Backup/etc/module.xml
+++ b/app/code/Magento/Backup/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Backup" version="1.6.0.0" active="true">
+    <module name="Magento_Backup" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
index ac700c144f5..00438ad0d5d 100644
--- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
+++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php
@@ -303,8 +303,12 @@ class Calculator implements BundleCalculatorInterface
     public function createSelectionPriceList($option, $bundleProduct)
     {
         $priceList = [];
+        $selections = $option->getSelections();
+        if ($selections === null) {
+            return $priceList;
+        }
         /* @var $selection \Magento\Bundle\Model\Selection|\Magento\Catalog\Model\Product */
-        foreach ($option->getSelections() as $selection) {
+        foreach ($selections as $selection) {
             if (!$selection->isSalable()) {
                 // @todo CatalogInventory Show out of stock Products
                 continue;
diff --git a/app/code/Magento/Bundle/etc/module.xml b/app/code/Magento/Bundle/etc/module.xml
index 8c1f43a62a0..8184420b5d5 100644
--- a/app/code/Magento/Bundle/etc/module.xml
+++ b/app/code/Magento/Bundle/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Bundle" version="1.6.0.0.2" active="true">
+    <module name="Magento_Bundle" schema_version="1.6.0.0.2" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/Captcha/etc/module.xml b/app/code/Magento/Captcha/etc/module.xml
index 4bc5e602611..71cade06549 100644
--- a/app/code/Magento/Captcha/etc/module.xml
+++ b/app/code/Magento/Captcha/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Captcha" version="1.7.0.0.0" active="true">
+    <module name="Magento_Captcha" schema_version="1.7.0.0.0" active="true">
         <sequence>
             <module name="Magento_Customer"/>
             <module name="Magento_Checkout"/>
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php
index 23228c4a1cb..3fda0549932 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php
@@ -59,23 +59,13 @@ class Sortby extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
     public function validate($object)
     {
         $attributeCode = $this->getAttribute()->getName();
-        $postDataConfig = $object->getData('use_post_data_config');
-        if ($postDataConfig) {
-            $isUseConfig = in_array($attributeCode, $postDataConfig);
-        } else {
-            $isUseConfig = false;
-            $postDataConfig = array();
-        }
+        $postDataConfig = $object->getData('use_post_data_config') ?: array();
+        $isUseConfig = in_array($attributeCode, $postDataConfig);
 
         if ($this->getAttribute()->getIsRequired()) {
             $attributeValue = $object->getData($attributeCode);
-            if ($this->getAttribute()->isValueEmpty($attributeValue)) {
-                if (is_array($attributeValue) && count($attributeValue) > 0) {
-                } else {
-                    if (!$isUseConfig) {
-                        return false;
-                    }
-                }
+            if ($this->getAttribute()->isValueEmpty($attributeValue) && !$isUseConfig) {
+                return false;
             }
         }
 
@@ -87,30 +77,21 @@ class Sortby extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
         }
 
         if ($attributeCode == 'default_sort_by') {
-            if ($available = $object->getData('available_sort_by')) {
-                if (!is_array($available)) {
-                    $available = explode(',', $available);
-                }
-                $data = !in_array(
-                    'default_sort_by',
-                    $postDataConfig
-                ) ? $object->getData(
-                    $attributeCode
-                ) : $this->_scopeConfig->getValue(
-                    "catalog/frontend/default_sort_by",
-                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            $available = $object->getData('available_sort_by') ?: array();
+            $available = is_array($available) ? $available : explode(',', $available);
+            $data = !in_array(
+                'default_sort_by',
+                $postDataConfig
+            ) ? $object->getData(
+                $attributeCode
+            ) : $this->_scopeConfig->getValue(
+                "catalog/frontend/default_sort_by",
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            );
+            if (!in_array($data, $available) && !in_array('available_sort_by', $postDataConfig)) {
+                throw new \Magento\Framework\Model\Exception(
+                    __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.')
                 );
-                if (!in_array($data, $available)) {
-                    throw new \Magento\Framework\Model\Exception(
-                        __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.')
-                    );
-                }
-            } else {
-                if (!in_array('available_sort_by', $postDataConfig)) {
-                    throw new \Magento\Framework\Model\Exception(
-                        __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.')
-                    );
-                }
             }
         }
 
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php
index f9ed2f4463b..feefc513de9 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php
@@ -32,6 +32,7 @@ class Mode extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
 {
     /**
      * {@inheritdoc}
+     * @codeCoverageIgnore
      */
     public function getAllOptions()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/ListMode.php b/app/code/Magento/Catalog/Model/Config/Source/ListMode.php
index d1ea806813d..b812221de11 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/ListMode.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/ListMode.php
@@ -27,6 +27,8 @@ class ListMode implements \Magento\Framework\Option\ArrayInterface
 {
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php b/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php
index a16018e08e3..45965b89011 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php
@@ -27,6 +27,8 @@ class Scope implements \Magento\Framework\Option\ArrayInterface
 {
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php b/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php
index 3ae5e666177..7aa4dde94c5 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php
@@ -27,6 +27,8 @@ class Step implements \Magento\Framework\Option\ArrayInterface
 {
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
index 68fe07a697c..6ac0f4429ac 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php
@@ -32,6 +32,8 @@ class Price implements \Magento\Framework\Option\ArrayInterface
 {
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php
index cb4bcb7215a..dc478debc2d 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php
@@ -35,6 +35,8 @@ class Thumbnail implements \Magento\Framework\Option\ArrayInterface
 
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php b/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php
index f3a188164cf..b467ba85b32 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php
@@ -27,6 +27,8 @@ class TimeFormat implements \Magento\Framework\Option\ArrayInterface
 {
     /**
      * {@inheritdoc}
+     *
+     * @codeCoverageIgnore
      */
     public function toOptionArray()
     {
diff --git a/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php b/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php
index 9ed316cbf97..b9b5ccd8e1b 100644
--- a/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php
+++ b/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php
@@ -35,6 +35,7 @@ class Position implements \Magento\Framework\Option\ArrayInterface
     /**
      * Get available options
      *
+     * @codeCoverageIgnore
      * @return array
      */
     public function toOptionArray()
diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php b/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php
index cc37f0b9642..bc434112ad1 100644
--- a/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php
+++ b/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php
@@ -58,8 +58,8 @@ class Decimal extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter
         array $data = array()
     ) {
         $this->_resource = $filterDecimalFactory->create();
-        parent::__construct($filterItemFactory, $storeManager, $layer, $data);
         $this->_requestVar = 'decimal';
+        parent::__construct($filterItemFactory, $storeManager, $layer, $data);
     }
 
     /**
@@ -86,7 +86,7 @@ class Decimal extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter
          * Filter must be string: $index, $range
          */
         $filter = $request->getParam($this->getRequestVar());
-        if (!$filter) {
+        if (!$filter || is_array($filter)) {
             return $this;
         }
 
diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Price.php b/app/code/Magento/Catalog/Model/Layer/Filter/Price.php
index 460891d3f66..78adcb1eb05 100644
--- a/app/code/Magento/Catalog/Model/Layer/Filter/Price.php
+++ b/app/code/Magento/Catalog/Model/Layer/Filter/Price.php
@@ -417,7 +417,7 @@ class Price extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter
          * Filter must be string: $fromPrice-$toPrice
          */
         $filter = $request->getParam($this->getRequestVar());
-        if (!$filter) {
+        if (!$filter || is_array($filter)) {
             return $this;
         }
 
diff --git a/app/code/Magento/Catalog/Model/Layer/State.php b/app/code/Magento/Catalog/Model/Layer/State.php
index 13cdccbb8cc..374fc4969b1 100644
--- a/app/code/Magento/Catalog/Model/Layer/State.php
+++ b/app/code/Magento/Catalog/Model/Layer/State.php
@@ -23,17 +23,21 @@
  */
 namespace Magento\Catalog\Model\Layer;
 
+use Magento\Catalog\Model\Layer\Filter\Item;
+use Magento\Framework\Model\Exception;
+use Magento\Framework\Object;
+
 /**
  * Layered navigation state model
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class State extends \Magento\Framework\Object
+class State extends Object
 {
     /**
      * Add filter item to layer state
      *
-     * @param   \Magento\Catalog\Model\Layer\Filter\Item $filter
+     * @param   Item $filter
      * @return  $this
      */
     public function addFilter($filter)
@@ -47,14 +51,14 @@ class State extends \Magento\Framework\Object
     /**
      * Set layer state filter items
      *
-     * @param  array $filters
+     * @param  Item[] $filters
      * @return $this
-     * @throws \Magento\Framework\Model\Exception
+     * @throws Exception
      */
     public function setFilters($filters)
     {
         if (!is_array($filters)) {
-            throw new \Magento\Framework\Model\Exception(__('The filters must be an array.'));
+            throw new Exception(__('The filters must be an array.'));
         }
         $this->setData('filters', $filters);
         return $this;
@@ -63,7 +67,7 @@ class State extends \Magento\Framework\Object
     /**
      * Get applied to layer filter items
      *
-     * @return array
+     * @return Item[]
      */
     public function getFilters()
     {
diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php
index ff187dc7908..99317d82065 100644
--- a/app/code/Magento/Catalog/Model/Product.php
+++ b/app/code/Magento/Catalog/Model/Product.php
@@ -622,7 +622,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements IdentityIn
      *
      * @param int  $groupId   Retrieve attributes of the specified group
      * @param bool $skipSuper Not used
-     * @return array
+     * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[]
      */
     public function getAttributes($groupId = null, $skipSuper = false)
     {
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php
index 3f007f47d41..5c0b8788978 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php
@@ -172,9 +172,7 @@ class Media extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
         if ($this->getAttribute()->getIsRequired()) {
             $value = $object->getData($this->getAttribute()->getAttributeCode());
             if ($this->getAttribute()->isValueEmpty($value)) {
-                if (!(is_array($value) && count($value) > 0)) {
-                    return false;
-                }
+                return false;
             }
         }
         if ($this->getAttribute()->getIsUnique()) {
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php
index bf512d3b159..d90a58cebf5 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php
@@ -53,19 +53,17 @@ class Image extends \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFronten
      * Returns url to product image
      *
      * @param  \Magento\Catalog\Model\Product $product
+     *
      * @return string|false
      */
     public function getUrl($product)
     {
         $image = $product->getData($this->getAttribute()->getAttributeCode());
-        if ($image) {
-            $url = $this->_storeManager->getStore(
-                $product->getStore()
-            )->getBaseUrl(
-                \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
-            ) . 'catalog/product/' . $image;
-        } else {
-            $url = false;
+        $url = false;
+        if (!empty($image)) {
+            $url = $this->_storeManager->getStore($product->getStore())
+                ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA)
+                . 'catalog/product/' . $image;
         }
         return $url;
     }
diff --git a/app/code/Magento/Catalog/Model/Product/Condition.php b/app/code/Magento/Catalog/Model/Product/Condition.php
index 6339d7a3f55..16e7fd353f3 100644
--- a/app/code/Magento/Catalog/Model/Product/Condition.php
+++ b/app/code/Magento/Catalog/Model/Product/Condition.php
@@ -23,14 +23,21 @@
  */
 namespace Magento\Catalog\Model\Product;
 
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\Framework\DB\Select;
-use Magento\Eav\Model\Entity\Collection\AbstractCollection;
 
+/**
+ * @method string getPkFieldName()
+ * @method Condition setPkFieldName(string $fieldName)
+ * @method string|array getTable()
+ * @method Condition setTable($table)
+ */
 class Condition extends \Magento\Framework\Object implements \Magento\Catalog\Model\Product\Condition\ConditionInterface
 {
     /**
      * @param AbstractCollection $collection
+     *
      * @return $this
      */
     public function applyToCollection($collection)
@@ -47,6 +54,7 @@ class Condition extends \Magento\Framework\Object implements \Magento\Catalog\Mo
 
     /**
      * @param AdapterInterface $dbAdapter
+     *
      * @return Select|string
      */
     public function getIdsSelect($dbAdapter)
diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php
index ad7163ce186..d6e9f7754e1 100644
--- a/app/code/Magento/Catalog/Model/Product/Option.php
+++ b/app/code/Magento/Catalog/Model/Product/Option.php
@@ -515,27 +515,6 @@ class Option extends AbstractModel
         return $collection;
     }
 
-    /**
-     * Prepare array of options for duplicate
-     *
-     * @return array
-     */
-    public function prepareOptionForDuplicate()
-    {
-        $this->setProductId(null);
-        $this->setOptionId(null);
-        $newOption = $this->__toArray();
-        if ($_values = $this->getValues()) {
-            $newValuesArray = array();
-            foreach ($_values as $_value) {
-                $newValuesArray[] = $_value->prepareValueForDuplicate();
-            }
-            $newOption['values'] = $newValuesArray;
-        }
-
-        return $newOption;
-    }
-
     /**
      * Duplicate options for product
      *
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php
index d2e3d4b9a9b..dcc8d625a4f 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Value.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php
@@ -294,19 +294,6 @@ class Value extends \Magento\Framework\Model\AbstractModel
         return $this;
     }
 
-    /**
-     * Prepare array of option values for duplicate
-     *
-     * @return array
-     */
-    public function prepareValueForDuplicate()
-    {
-        $this->setOptionId(null);
-        $this->setOptionTypeId(null);
-
-        return $this->__toArray();
-    }
-
     /**
      * Duplicate product options value
      *
diff --git a/app/code/Magento/Catalog/Model/Product/Type.php b/app/code/Magento/Catalog/Model/Product/Type.php
index a4f650371db..7f7e1f776e2 100644
--- a/app/code/Magento/Catalog/Model/Product/Type.php
+++ b/app/code/Magento/Catalog/Model/Product/Type.php
@@ -219,11 +219,8 @@ class Type
      */
     public function getAllOptions()
     {
-        $res = array();
-        $res[] = array('value' => '', 'label' => '');
-        foreach ($this->getOptionArray() as $index => $value) {
-            $res[] = array('value' => $index, 'label' => $value);
-        }
+        $res = $this->getOptions();
+        array_unshift($res, ['value' => '', 'label' => '']);
         return $res;
     }
 
@@ -234,9 +231,9 @@ class Type
      */
     public function getOptions()
     {
-        $res = array();
+        $res = [];
         foreach ($this->getOptionArray() as $index => $value) {
-            $res[] = array('value' => $index, 'label' => $value);
+            $res[] = ['value' => $index, 'label' => $value];
         }
         return $res;
     }
diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
index 902ef537358..eaab2830dd4 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
@@ -263,7 +263,7 @@ abstract class AbstractType
      * Get array of product set attributes
      *
      * @param \Magento\Catalog\Model\Product $product
-     * @return array
+     * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[]
      */
     public function getSetAttributes($product)
     {
@@ -297,7 +297,7 @@ abstract class AbstractType
      * Retrieve product type attributes
      *
      * @param \Magento\Catalog\Model\Product $product
-     * @return array
+     * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[]
      */
     public function getEditableAttributes($product)
     {
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php
index 33c971db73b..924bd369d2a 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php
@@ -33,6 +33,7 @@ class Attribute extends AbstractObject
     const IS_USER_DEFINED = 'is_user_defined';
     const LABEL = 'frontend_label';
     const DEFAULT_VALUE = 'default_value';
+    const FRONTEND_INPUT = 'frontend_input';
 
     /**
      * Get attribute ID
@@ -95,4 +96,14 @@ class Attribute extends AbstractObject
     {
         return $this->_get(self::IS_USER_DEFINED);
     }
+
+    /**
+     * Get frontend input type
+     *
+     * @return string
+     */
+    public function getFrontendInput()
+    {
+        return $this->_get(self::FRONTEND_INPUT);
+    }
 }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php
index 55cbfbabcc4..9729c8b1464 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php
@@ -92,4 +92,15 @@ class AttributeBuilder extends AbstractObjectBuilder
     {
         return $this->_set(Attribute::IS_USER_DEFINED, $isUserDefined);
     }
+
+    /**
+     * Set frontend input type
+     *
+     * @param string $type
+     * @return $this
+     */
+    public function setFrontendInput($type)
+    {
+        return $this->_set(Attribute::FRONTEND_INPUT, $type);
+    }
 }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php
index 5606c3f7b04..2adec8b2921 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php
@@ -23,10 +23,12 @@
  */
 namespace Magento\Catalog\Service\V1\Data\Eav;
 
+use \Magento\Framework\Service\Data\Eav\AbstractObject;
+
 /**
  * Class AttributeMetadata
  */
-class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
+class AttributeMetadata extends AbstractObject
 {
     /**#@+
      * Constants used as keys into $_data
@@ -41,6 +43,8 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
 
     const OPTIONS = 'options';
 
+    const SYSTEM = 'system';
+
     const VISIBLE = 'visible';
 
     const REQUIRED = 'required';
@@ -53,6 +57,10 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
 
     const BACKEND_TYPE = 'backend_type';
 
+    const SOURCE_MODEL = 'source_model';
+
+    const BACKEND_MODEL = 'backend_model';
+
     const DEFAULT_VALUE = 'default_value';
 
     const UNIQUE = 'unique';
@@ -94,7 +102,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Retrieve id of the attribute.
      *
-     * @return string
+     * @return string|null
      */
     public function getAttributeId()
     {
@@ -104,17 +112,27 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Retrieve code of the attribute.
      *
-     * @return string
+     * @return string|null
      */
     public function getAttributeCode()
     {
         return $this->_get(self::ATTRIBUTE_CODE);
     }
 
+    /**
+     * Retrieve is system attribute flag
+     *
+     * @return bool|null
+     */
+    public function isSystem()
+    {
+        return $this->_get(self::SYSTEM);
+    }
+
     /**
      * Frontend HTML for input element.
      *
-     * @return string
+     * @return string|null
      */
     public function getFrontendInput()
     {
@@ -124,7 +142,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Retrieve validation rules.
      *
-     * @return \Magento\Catalog\Service\V1\Data\Eav\ValidationRule[]
+     * @return \Magento\Catalog\Service\V1\Data\Eav\ValidationRule[]|null
      */
     public function getValidationRules()
     {
@@ -134,7 +152,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether attribute is visible on frontend.
      *
-     * @return bool
+     * @return bool|null
      */
     public function isVisible()
     {
@@ -144,7 +162,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether attribute is required.
      *
-     * @return bool
+     * @return bool|null
      */
     public function isRequired()
     {
@@ -154,7 +172,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Return options of the attribute (key => value pairs for select)
      *
-     * @return \Magento\Catalog\Service\V1\Data\Eav\Option[]
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Option[]|null
      */
     public function getOptions()
     {
@@ -164,7 +182,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether current attribute has been defined by a user.
      *
-     * @return bool
+     * @return bool|null
      */
     public function isUserDefined()
     {
@@ -174,7 +192,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get label which supposed to be displayed on frontend.
      *
-     * @return string
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel[]|null
      */
     public function getFrontendLabel()
     {
@@ -184,7 +202,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get the note attribute for the element.
      *
-     * @return string
+     * @return string|null
      */
     public function getNote()
     {
@@ -194,17 +212,37 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get backend type.
      *
-     * @return string
+     * @return string|null
      */
     public function getBackendType()
     {
         return $this->_get(self::BACKEND_TYPE);
     }
 
+    /**
+     * Get backend model
+     *
+     * @return string|null
+     */
+    public function getBackendModel()
+    {
+        return $this->_get(self::BACKEND_MODEL);
+    }
+
+    /**
+     * Get source model
+     *
+     * @return string|null
+     */
+    public function getSourceModel()
+    {
+        return $this->_get(self::SOURCE_MODEL);
+    }
+
     /**
      * Get default value for the element.
      *
-     * @return string
+     * @return string|null
      */
     public function getDefaultValue()
     {
@@ -214,7 +252,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether this is a unique attribute
      *
-     * @return string
+     * @return string|null
      */
     public function isUnique()
     {
@@ -233,7 +271,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
      *  - 'bundle',
      *  - 'downloadable'
      *
-     * @return string[]
+     * @return string[]|null
      */
     public function getApplyTo()
     {
@@ -243,7 +281,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be used for configurable products
      *
-     * @return string
+     * @return string|null
      */
     public function isConfigurable()
     {
@@ -253,7 +291,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be used in Quick Search
      *
-     * @return string
+     * @return string|null
      */
     public function isSearchable()
     {
@@ -263,7 +301,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be used in Advanced Search
      *
-     * @return string
+     * @return string|null
      */
     public function isVisibleInAdvancedSearch()
     {
@@ -273,7 +311,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be compared on the frontend
      *
-     * @return string
+     * @return string|null
      */
     public function isComparable()
     {
@@ -283,7 +321,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be used for promo rules
      *
-     * @return string
+     * @return string|null
      */
     public function isUsedForPromoRules()
     {
@@ -293,7 +331,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute is visible on the frontend
      *
-     * @return string
+     * @return string|null
      */
     public function isVisibleOnFront()
     {
@@ -303,7 +341,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the attribute can be used in product listing
      *
-     * @return string
+     * @return string|null
      */
     public function getUsedInProductListing()
     {
@@ -313,7 +351,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Retrieve attribute scope
      *
-     * @return string
+     * @return string|null
      */
     public function getScope()
     {
@@ -323,7 +361,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Retrieve frontend class of attribute
      *
-     * @return string
+     * @return string|null
      */
     public function getFrontendClass()
     {
@@ -333,7 +371,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Enable WYSIWYG flag
      *
-     * @return bool
+     * @return bool|null
      */
     public function isWysiwygEnabled()
     {
@@ -343,7 +381,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether the HTML tags are allowed on the frontend
      *
-     * @return bool
+     * @return bool|null
      */
     public function isHtmlAllowedOnFront()
     {
@@ -353,7 +391,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether it is used for sorting in product listing
      *
-     * @return bool
+     * @return bool|null
      * @SuppressWarnings(PHPMD.BooleanGetMethodName)
      */
     public function getUsedForSortBy()
@@ -364,7 +402,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether it used in layered navigation
      *
-     * @return bool
+     * @return bool|null
      */
     public function isFilterable()
     {
@@ -374,7 +412,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Whether it is used in search results layered navigation
      *
-     * @return bool
+     * @return bool|null
      */
     public function isFilterableInSearch()
     {
@@ -384,7 +422,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get position
      *
-     * @return int
+     * @return int|null
      */
     public function getPosition()
     {
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php
index 3e996fa2ad3..7da8259f70e 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php
@@ -23,8 +23,7 @@
  */
 namespace Magento\Catalog\Service\V1\Data\Eav;
 
-use Magento\Framework\Service\Data\AbstractObjectBuilder;
-use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Framework\Service\Data\Eav\AbstractObjectBuilder;
 
 /**
  * Class AttributeMetadataBuilder
@@ -45,23 +44,34 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
      */
     protected $validationRuleBuilder;
 
+    /**
+     * @var Product\Attribute\FrontendLabelBuilder
+     */
+    protected $frontendLabelBuilder;
+
     /**
      * Initializes builder.
      *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param \Magento\Framework\Service\Data\Eav\AttributeValueBuilder $valueBuilder
      * @param OptionBuilder $optionBuilder
      * @param ValidationRuleBuilder $validationRuleBuilder
-     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param Product\Attribute\FrontendLabelBuilder $frontendLabelBuilder
      */
     public function __construct(
         \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        \Magento\Framework\Service\Data\Eav\AttributeValueBuilder $valueBuilder,
         OptionBuilder $optionBuilder,
-        ValidationRuleBuilder $validationRuleBuilder
+        ValidationRuleBuilder $validationRuleBuilder,
+        Product\Attribute\FrontendLabelBuilder $frontendLabelBuilder
     ) {
-        parent::__construct($objectFactory);
+        parent::__construct($objectFactory, $valueBuilder);
         $this->optionBuilder = $optionBuilder;
         $this->validationRuleBuilder = $validationRuleBuilder;
+        $this->frontendLabelBuilder = $frontendLabelBuilder;
         $this->_data[AttributeMetadata::OPTIONS] = array();
         $this->_data[AttributeMetadata::VALIDATION_RULES] = array();
+        $this->_data[AttributeMetadata::FRONTEND_LABEL] = array();
     }
 
     /**
@@ -86,6 +96,17 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
         return $this->_set(AttributeMetadata::ATTRIBUTE_CODE, $attributeCode);
     }
 
+    /**
+     * Set whether the attribute system or not
+     *
+     * @param  bool $isSystem
+     * @return $this
+     */
+    public function setSystem($isSystem)
+    {
+        return $this->_set(AttributeMetadata::SYSTEM, $isSystem);
+    }
+
     /**
      * Set front end input
      *
@@ -155,7 +176,7 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
     /**
      * Set front end label
      *
-     * @param  string $frontendLabel
+     * @param  \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel[] $frontendLabel
      * @return $this
      */
     public function setFrontendLabel($frontendLabel)
@@ -183,6 +204,28 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
         return $this->_set(AttributeMetadata::BACKEND_TYPE, $backendType);
     }
 
+    /**
+     * Set backend model
+     *
+     * @param  string $value
+     * @return $this
+     */
+    public function setBackendModel($value)
+    {
+        return $this->_set(AttributeMetadata::BACKEND_MODEL, $value);
+    }
+
+    /**
+     * Set source model
+     *
+     * @param  string $value
+     * @return $this
+     */
+    public function setSourceModel($value)
+    {
+        return $this->_set(AttributeMetadata::SOURCE_MODEL, $value);
+    }
+
     /**
      * Set default value for the element
      *
@@ -411,6 +454,7 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
 
     /**
      * {@inheritdoc}
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     protected function _setDataValues(array $data)
     {
@@ -432,6 +476,15 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder
             $data[AttributeMetadata::VALIDATION_RULES] = $validationRules;
         }
 
+        // fill frontend labels
+        if (isset($data[AttributeMetadata::FRONTEND_LABEL]) && is_array($data[AttributeMetadata::FRONTEND_LABEL])) {
+            $frontendLabel = [];
+            foreach ($data[AttributeMetadata::FRONTEND_LABEL] as $key => $value) {
+                $frontendLabel[$key] = $this->frontendLabelBuilder->populateWithArray($value)->create();
+            }
+            $data[AttributeMetadata::FRONTEND_LABEL] = $frontendLabel;
+        }
+
         if (array_key_exists(AttributeMetadata::APPLY_TO, $data)) {
             $data[AttributeMetadata::APPLY_TO] = $this->processApplyToValue($data[AttributeMetadata::APPLY_TO]);
         }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php
index 4bb117b3697..19cbe278dcd 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php
@@ -37,6 +37,12 @@ class Option extends \Magento\Framework\Service\Data\AbstractObject
 
     const VALUE = 'value';
 
+    const ORDER = 'order';
+
+    const STORE_LABELS = 'store_labels';
+
+    const IS_DEFAULT = 'default';
+
     /**
      * Get option label
      *
@@ -50,10 +56,40 @@ class Option extends \Magento\Framework\Service\Data\AbstractObject
     /**
      * Get option value
      *
-     * @return string
+     * @return string|null
      */
     public function getValue()
     {
         return $this->_get(self::VALUE);
     }
+
+    /**
+     * Get option order
+     *
+     * @return int|null
+     */
+    public function getOrder()
+    {
+        return $this->_get(self::ORDER);
+    }
+
+    /**
+     * is default
+     *
+     * @return bool|null
+     */
+    public function isDefault()
+    {
+        return $this->_get(self::IS_DEFAULT);
+    }
+
+    /**
+     * Set option label for store scopes
+     *
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Option\Label[]|null
+     */
+    public function getStoreLabels()
+    {
+        return $this->_get(Option::STORE_LABELS);
+    }
 }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php
new file mode 100644
index 00000000000..44b449ff673
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Eav attribute option
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Data\Eav\Option;
+
+/**
+ * Class Store Scope Label
+ */
+class Label extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**
+     * Constants used as keys into $_data
+     */
+    const LABEL = 'label';
+    const STORE_ID = 'store_id';
+
+    /**
+     * Get option label
+     *
+     * @return string
+     */
+    public function getLabel()
+    {
+        return $this->_get(self::LABEL);
+    }
+
+    /**
+     * Get store id
+     *
+     * @return int
+     */
+    public function getStoreId()
+    {
+        return $this->_get(self::STORE_ID);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php
new file mode 100644
index 00000000000..67b10003e1c
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Data\Eav\Option;
+
+/**
+ * Class LabelBuilder
+ */
+class LabelBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Set option label
+     *
+     * @param  string $label
+     * @return $this
+     */
+    public function setLabel($label)
+    {
+        return $this->_set(Label::LABEL, $label);
+    }
+
+    /**
+     * Set store id
+     *
+     * @param int $value
+     * @return $this
+     */
+    public function setStoreId($value)
+    {
+        return $this->_set(Label::STORE_ID, $value);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php
index 893e33265e9..cd7d935cf10 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php
@@ -49,4 +49,37 @@ class OptionBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilde
     {
         return $this->_set(Option::VALUE, $value);
     }
+
+    /**
+     * Get option label
+     *
+     * @param int $value
+     * @return $this
+     */
+    public function setOrder($value)
+    {
+        return $this->_set(Option::ORDER, $value);
+    }
+
+    /**
+     * Get option order
+     *
+     * @param bool $value
+     * @return $this
+     */
+    public function setDefault($value)
+    {
+        return $this->_set(Option::IS_DEFAULT, $value);
+    }
+
+    /**
+     * Set option label for store scope
+     *
+     * @param  \Magento\Catalog\Service\V1\Data\Eav\Option\Label[] $value
+     * @return $this
+     */
+    public function setStoreLabels($value)
+    {
+        return $this->_set(Option::STORE_LABELS, $value);
+    }
 }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php
new file mode 100644
index 00000000000..35fe1447671
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute;
+
+/**
+ * Class FrontendLabel
+ * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute
+ */
+class FrontendLabel extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**
+     * Constants used as keys into $_data
+     */
+    const STORE_ID = 'store_id';
+
+    const LABEL = 'label';
+
+    /**
+     * Get store id value
+     *
+     * @return string
+     */
+    public function getStoreId()
+    {
+        return $this->_get(self::STORE_ID);
+    }
+
+    /**
+     * Get label
+     *
+     * @return string
+     */
+    public function getLabel()
+    {
+        return $this->_get(self::LABEL);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php
new file mode 100644
index 00000000000..d5760cdc196
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute;
+
+/**
+ * Class FrontendLabelBuilder
+ * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute
+ */
+class FrontendLabelBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Set store id value
+     *
+     * @param  string $value
+     * @return $this
+     */
+    public function setStoreId($value)
+    {
+        return $this->_set(FrontendLabel::STORE_ID, $value);
+    }
+
+    /**
+     * Set label
+     *
+     * @param  string $label
+     * @return $this
+     */
+    public function setLabel($label)
+    {
+        return $this->_set(FrontendLabel::LABEL, $label);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php
similarity index 86%
rename from app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php
rename to app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php
index c4f1778b981..dbc20c98100 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php
@@ -21,13 +21,13 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Service\V1\Data;
+namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute;
 
 /**
- * Class ProductAttributeType
- * @package Magento\Catalog\Service\V1\Data
+ * Class Type
+ * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute
  */
-class ProductAttributeType extends \Magento\Framework\Service\Data\AbstractObject
+class Type extends \Magento\Framework\Service\Data\AbstractObject
 {
     /**
      * Constants used as keys into $_data
diff --git a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php
similarity index 77%
rename from app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php
rename to app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php
index 570e9a581d5..b10dbb881c6 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php
+++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php
@@ -21,13 +21,13 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Service\V1\Data;
+namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute;
 
 /**
- * Class ProductAttributeTypeBuilder
- * @package Magento\Catalog\Service\V1\Data\Eav
+ * Class TypeBuilder
+ * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute
  */
-class ProductAttributeTypeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+class TypeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
 {
     /**
      * Set option label
@@ -37,7 +37,7 @@ class ProductAttributeTypeBuilder extends \Magento\Framework\Service\Data\Abstra
      */
     public function setLabel($label)
     {
-        return $this->_set(ProductAttributeType::LABEL, $label);
+        return $this->_set(Type::LABEL, $label);
     }
 
     /**
@@ -48,6 +48,6 @@ class ProductAttributeTypeBuilder extends \Magento\Framework\Service\Data\Abstra
      */
     public function setValue($value)
     {
-        return $this->_set(ProductAttributeType::VALUE, $value);
+        return $this->_set(Type::VALUE, $value);
     }
 }
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php
new file mode 100644
index 00000000000..01659feb567
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Service\V1\Data\Product\Attribute;
+
+/**
+ * SearchResults Service Data Object used for the search service requests
+ */
+class SearchResults extends \Magento\Framework\Service\V1\Data\SearchResults
+{
+    /**
+     * Get items
+     *
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Attribute[]
+     */
+    public function getItems()
+    {
+        return parent::getItems();
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResultsBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResultsBuilder.php
new file mode 100644
index 00000000000..dda2b0bbd81
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResultsBuilder.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Service\V1\Data\Product\Attribute;
+
+use Magento\Framework\Service\Data\ObjectFactory;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+use Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder;
+use Magento\Catalog\Service\V1\Data\Eav\AttributeBuilder;
+
+/**
+ * Builder for the SearchResults Service Data Object
+ *
+ * @method \Magento\Catalog\Service\V1\Data\Product\Attribute\SearchResults create()
+ */
+class SearchResultsBuilder extends \Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder
+{
+    /**
+     * Constructor
+     *
+     * @param ObjectFactory $objectFactory
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param AttributeBuilder $attributeBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        AttributeBuilder $attributeBuilder
+    ) {
+        parent::__construct($objectFactory, $searchCriteriaBuilder, $attributeBuilder);
+    }
+
+    /**
+     * Set items
+     *
+     * @param \Magento\Catalog\Service\V1\Data\Eav\Attribute[] $items
+     * @return $this
+     */
+    public function setItems($items)
+    {
+        return parent::setItems($items);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResults.php b/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResults.php
new file mode 100644
index 00000000000..6061fbe257b
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResults.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Service\V1\Data\Product;
+
+/**
+ * SearchResults Service Data Object used for the search service requests
+ */
+class SearchResults extends \Magento\Framework\Service\V1\Data\SearchResults
+{
+    /**
+     * Get items
+     *
+     * @return \Magento\Catalog\Service\V1\Data\Product[]
+     */
+    public function getItems()
+    {
+        return parent::getItems();
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResultsBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResultsBuilder.php
new file mode 100644
index 00000000000..914a5be932a
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Data/Product/SearchResultsBuilder.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Catalog\Service\V1\Data\Product;
+
+use Magento\Framework\Service\Data\ObjectFactory;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+use Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder;
+use Magento\Catalog\Service\V1\Data\ProductBuilder;
+
+/**
+ * Builder for the SearchResults Service Data Object
+ *
+ * @method \Magento\Catalog\Service\V1\Data\Product\SearchResults create()
+ */
+class SearchResultsBuilder extends AbstractSearchResultsBuilder
+{
+    /**
+     * Constructor
+     *
+     * @param ObjectFactory $objectFactory
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param ProductBuilder $productBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        ProductBuilder $productBuilder
+    ) {
+        parent::__construct($objectFactory, $searchCriteriaBuilder, $productBuilder);
+    }
+
+    /**
+     * Set items
+     *
+     * @param \Magento\Catalog\Service\V1\Data\Product[] $items
+     * @return $this
+     */
+    public function setItems($items)
+    {
+        return parent::setItems($items);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadService.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadService.php
new file mode 100644
index 00000000000..34124b5915e
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadService.php
@@ -0,0 +1,227 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+use Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory;
+use Magento\Catalog\Service\V1\Data\Eav\Attribute;
+use Magento\Catalog\Service\V1\Data\Eav\AttributeBuilder;
+use Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\TypeBuilder;
+use Magento\Catalog\Service\V1\Data\Product\Attribute\SearchResultsBuilder;
+use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
+use Magento\Eav\Model\Resource\Entity\Attribute\Collection;
+use Magento\Framework\Service\V1\Data\Search\FilterGroup;
+use Magento\Framework\Service\V1\Data\SearchCriteria;
+
+/**
+ * Class ReadService
+ *
+ * @package Magento\Catalog\Service\V1\Product\Attribute
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ReadService implements ReadServiceInterface
+{
+    /**
+     * @var ProductMetadataServiceInterface
+     */
+    private $metadataService;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory
+     */
+    private $inputTypeFactory;
+
+    /**
+     * @var TypeBuilder
+     */
+    private $attributeTypeBuilder;
+
+    /**
+     * @var SearchResultsBuilder
+     */
+    private $searchResultsBuilder;
+
+    /**
+     * @var Collection
+     */
+    private $attributeCollection;
+
+    /**
+     * @var AttributeBuilder
+     */
+    protected $attributeBuilder;
+
+    /**
+     * @param ProductMetadataServiceInterface $metadataService
+     * @param InputtypeFactory $inputTypeFactory
+     * @param SearchResultsBuilder $searchResultsBuilder
+     * @param \Magento\Eav\Model\Resource\Entity\Attribute\Collection $attributeCollection
+     * @param AttributeBuilder $attributeBuilder
+     * @param TypeBuilder $attributeTypeBuilder
+     */
+    public function __construct(
+        ProductMetadataServiceInterface $metadataService,
+        InputtypeFactory $inputTypeFactory,
+        SearchResultsBuilder $searchResultsBuilder,
+        \Magento\Eav\Model\Resource\Entity\Attribute\Collection $attributeCollection,
+        AttributeBuilder $attributeBuilder,
+        TypeBuilder $attributeTypeBuilder
+    ) {
+        $this->metadataService = $metadataService;
+        $this->inputTypeFactory = $inputTypeFactory;
+        $this->attributeTypeBuilder = $attributeTypeBuilder;
+        $this->searchResultsBuilder = $searchResultsBuilder;
+        $this->attributeCollection = $attributeCollection;
+        $this->attributeBuilder = $attributeBuilder;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function types()
+    {
+        $types = [];
+        $inputType = $this->inputTypeFactory->create();
+
+        foreach ($inputType->toOptionArray() as $option) {
+            $types[] = $this->attributeTypeBuilder->populateWithArray($option)->create();
+        }
+        return $types;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function info($id)
+    {
+        return $this->metadataService->getAttributeMetadata(
+            ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+            $id
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function search(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria)
+    {
+        $this->searchResultsBuilder->setSearchCriteria($searchCriteria);
+
+        //Add filters from root filter group to the collection
+        foreach ($searchCriteria->getFilterGroups() as $group) {
+            $this->addFilterGroupToCollection($group, $this->attributeCollection);
+        }
+        $sortOrders = $searchCriteria->getSortOrders();
+        if ($sortOrders) {
+            foreach ($searchCriteria->getSortOrders() as $field => $direction) {
+                $field = $this->translateField($field);
+                $this->attributeCollection->addOrder($field, $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC');
+            }
+        }
+        $this->attributeCollection->join(
+            array('additional_table' => $this->attributeCollection->getTable('catalog_eav_attribute')),
+            'main_table.attribute_id = additional_table.attribute_id',
+            [
+                'frontend_input_renderer',
+                'is_global',
+                'is_visible',
+                'is_searchable',
+                'is_filterable',
+                'is_comparable',
+                'is_visible_on_front',
+                'is_html_allowed_on_front',
+                'is_used_for_price_rules',
+                'is_filterable_in_search',
+                'used_in_product_listing',
+                'used_for_sort_by',
+                'apply_to',
+                'is_visible_in_advanced_search',
+                'position',
+                'is_wysiwyg_enabled',
+                'is_used_for_promo_rules',
+                'is_configurable',
+                'search_weight',
+            ]
+        );
+
+        $this->attributeCollection->setCurPage($searchCriteria->getCurrentPage());
+        $this->attributeCollection->setPageSize($searchCriteria->getPageSize());
+        $this->searchResultsBuilder->setTotalCount($this->attributeCollection->getSize());
+
+        $attributes = array();
+        /** @var \Magento\Eav\Model\Entity\Attribute $attribute */
+        foreach ($this->attributeCollection as $attribute) {
+            $attributes[] = $this->attributeBuilder->setId($attribute->getAttributeId())
+                ->setCode($attribute->getAttributeCode())
+                ->setFrontendLabel($attribute->getData('frontend_label'))
+                ->setDefaultValue($attribute->getDefaultValue())
+                ->setIsRequired((boolean)$attribute->getData('is_required'))
+                ->setIsUserDefined((boolean)$attribute->getData('is_user_defined'))
+                ->setFrontendInput($attribute->getData('frontend_input'))
+                ->create();
+        }
+
+        $this->searchResultsBuilder->setItems($attributes);
+        return $this->searchResultsBuilder->create();
+    }
+
+    /**
+     * Helper function that adds a FilterGroup to the collection.
+     *
+     * @param FilterGroup $filterGroup
+     * @param \Magento\Eav\Model\Resource\Entity\Attribute\Collection $collection
+     * @return void
+     * @throws \Magento\Framework\Exception\InputException
+     */
+    protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection)
+    {
+        $fields = [];
+        $conditions = [];
+        foreach ($filterGroup->getFilters() as $filter) {
+            $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
+            $fields[] = $this->translateField($filter->getField());
+            $conditions[] = [$condition => $filter->getValue()];
+        }
+        if ($fields) {
+            $collection->addFieldToFilter($fields, $conditions);
+        }
+    }
+
+    /**
+     * Translates a field name to a DB column name for use in collection queries.
+     *
+     * @param string $field a field name that should be translated to a DB column name.
+     * @return string
+     */
+    protected function translateField($field)
+    {
+        switch ($field) {
+            case Attribute::ID:
+                return 'attribute_id';
+            case Attribute::CODE:
+                return 'attribute_code';
+            default:
+                return $field;
+        }
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php
new file mode 100644
index 00000000000..c9e17e77c16
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+/**
+ * Class ReadServiceInterface
+ * @package Magento\Catalog\Service\V1\Product\Attribute
+ */
+interface ReadServiceInterface
+{
+    /**
+     * Retrieve list of product attribute types
+     *
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\Type[]
+     */
+    public function types();
+
+    /**
+     * Get full information about a required attribute with the list of options
+     *
+     * @param  string $id
+     * @return \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata
+     *
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function info($id);
+
+    /**
+     * Retrieve the list of product attributes
+     *
+     * @param \Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria
+     * @return \Magento\Catalog\Service\V1\Data\Product\Attribute\SearchResults containing Data\Eav\Attribute objects
+     */
+    public function search(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria);
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteService.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteService.php
new file mode 100644
index 00000000000..9edb7528dd1
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteService.php
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+use Magento\Framework\Service\EavDataObjectConverter;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Exception\CouldNotSaveException;
+use Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata;
+use Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel;
+use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
+
+/**
+ * Class WriteService
+ * @package Magento\Catalog\Service\V1\Product\Attribute
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class WriteService implements WriteServiceInterface
+{
+    /**
+     * @var \Magento\Eav\Model\Config
+     */
+    protected $eavConfig;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Eav\AttributeFactory
+     */
+    protected $attributeFactory;
+
+    /**
+     * @var \Magento\Framework\Filter\FilterManager
+     */
+    protected $filter;
+
+    /**
+     * @var \Magento\Catalog\Helper\Product
+     */
+    protected $helper;
+
+    /**
+     * @var \Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory
+     */
+    protected $inputtypeValidatorFactory;
+
+    /**
+     * @param \Magento\Eav\Model\Config $eavConfig
+     * @param \Magento\Catalog\Model\Resource\Eav\AttributeFactory $attributeFactory
+     * @param \Magento\Framework\Filter\FilterManager $filter
+     * @param \Magento\Catalog\Helper\Product $helper
+     * @param \Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory $inputtypeValidatorFactory
+     */
+    public function __construct(
+        \Magento\Eav\Model\Config $eavConfig,
+        \Magento\Catalog\Model\Resource\Eav\AttributeFactory $attributeFactory,
+        \Magento\Framework\Filter\FilterManager $filter,
+        \Magento\Catalog\Helper\Product $helper,
+        \Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory $inputtypeValidatorFactory
+    ) {
+        $this->eavConfig = $eavConfig;
+        $this->attributeFactory = $attributeFactory;
+        $this->filter = $filter;
+        $this->helper = $helper;
+        $this->inputtypeValidatorFactory = $inputtypeValidatorFactory;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function create(\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attributeMetadata)
+    {
+        /**
+         * @var $model \Magento\Catalog\Model\Resource\Eav\Attribute
+         */
+        $model = $this->attributeFactory->create();
+        $data = $attributeMetadata->__toArray();
+        // unset attribute id because we create new attribute (does not rewrite existing one)
+        unset($data[AttributeMetadata::ATTRIBUTE_ID]);
+
+        // define frontend label
+        if (!$attributeMetadata->getFrontendLabel()) {
+            throw InputException::requiredField(AttributeMetadata::FRONTEND_LABEL);
+        }
+        $data[AttributeMetadata::FRONTEND_LABEL] = [];
+        foreach ($attributeMetadata->getFrontendLabel() as $label) {
+            $data[AttributeMetadata::FRONTEND_LABEL][$label->getStoreId()] = $label->getLabel();
+        }
+        if (!isset($data[AttributeMetadata::FRONTEND_LABEL][0]) || !$data[AttributeMetadata::FRONTEND_LABEL][0]) {
+            throw InputException::invalidFieldValue(AttributeMetadata::FRONTEND_LABEL, null);
+        }
+
+        $data[AttributeMetadata::ATTRIBUTE_CODE] =
+            $attributeMetadata->getAttributeCode() ?: $this->generateCode($data[AttributeMetadata::FRONTEND_LABEL][0]);
+        $this->validateCode($data[AttributeMetadata::ATTRIBUTE_CODE]);
+        $this->validateFrontendInput($attributeMetadata->getFrontendInput());
+
+        $data[AttributeMetadata::BACKEND_TYPE] = $model->getBackendTypeByInput($attributeMetadata->getFrontendInput());
+        $data[AttributeMetadata::SOURCE_MODEL] =
+            $this->helper->getAttributeSourceModelByInputType($attributeMetadata->getFrontendInput());
+        $data[AttributeMetadata::BACKEND_MODEL] =
+            $this->helper->getAttributeBackendModelByInputType($attributeMetadata->getFrontendInput());
+
+        $model->addData($data);
+
+        $model->setEntityTypeId($this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId())
+            ->setIsUserDefined(1);
+
+        return $model->save()->getAttributeCode();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function update($id, AttributeMetadata $attribute)
+    {
+        /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attributeModel */
+        $model = $this->attributeFactory->create();
+        $model->loadByCode(\Magento\Catalog\Model\Product::ENTITY, $id);
+        if (!$model->getId()) {
+            throw NoSuchEntityException::singleField(AttributeMetadata::ATTRIBUTE_CODE, $id);
+        }
+
+        $data = $attribute->__toArray();
+
+        // this fields should not be changed
+        $data[AttributeMetadata::ATTRIBUTE_ID]   = $model->getAttributeId();
+        $data[AttributeMetadata::USER_DEFINED]   = $model->getIsUserDefined();
+        $data[AttributeMetadata::FRONTEND_INPUT] = $model->getFrontendInput();
+
+        if (isset($data[AttributeMetadata::FRONTEND_LABEL]) && is_array($data[AttributeMetadata::FRONTEND_LABEL])) {
+            $frontendLabel[0] = $model->getFrontendLabel();
+            foreach ($data[AttributeMetadata::FRONTEND_LABEL] as $item) {
+                if (isset($item[FrontendLabel::STORE_ID], $item[FrontendLabel::LABEL])) {
+                    $frontendLabel[$item[FrontendLabel::STORE_ID]] = $item[FrontendLabel::LABEL];
+                }
+            }
+            $data[AttributeMetadata::FRONTEND_LABEL] = $frontendLabel;
+        }
+
+        if (!$model->getIsUserDefined()) {
+            // Unset attribute field for system attributes
+            unset($data[AttributeMetadata::APPLY_TO]);
+        }
+
+        try {
+            $model->addData($data);
+            $model->save();
+        } catch (\Exception $e) {
+            throw new CouldNotSaveException('Could not update product attribute' . $e->getMessage());
+        }
+
+        return $model->getAttributeCode();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($attributeId)
+    {
+        $model = $this->eavConfig->getAttribute(ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, $attributeId);
+        if (!$model || !$model->getId()) {
+            //product attribute does not exist
+            throw NoSuchEntityException::singleField(AttributeMetadata::ATTRIBUTE_ID, $attributeId);
+        }
+        $model->delete();
+        return true;
+    }
+
+    /**
+     * Generate code from label
+     *
+     * @param string $label
+     * @return string
+     */
+    protected function generateCode($label)
+    {
+        $code = substr(preg_replace('/[^a-z_0-9]/', '_', $this->filter->translitUrl($label)), 0, 30);
+        $validatorAttrCode = new \Zend_Validate_Regex(array('pattern' => '/^[a-z][a-z_0-9]{0,29}[a-z0-9]$/'));
+        if (!$validatorAttrCode->isValid($code)) {
+            $code = 'attr_' . ($code ?: substr(md5(time()), 0, 8));
+        }
+        return $code;
+    }
+
+    /**
+     * Validate attribute code
+     *
+     * @param string $code
+     * @return void
+     * @throws \Magento\Framework\Exception\InputException
+     */
+    protected function validateCode($code)
+    {
+        $validatorAttrCode = new \Zend_Validate_Regex(array('pattern' => '/^[a-z][a-z_0-9]{0,30}$/'));
+        if (!$validatorAttrCode->isValid($code)) {
+            throw InputException::invalidFieldValue('attribute_code', $code);
+        }
+    }
+
+    /**
+     * Validate Frontend Input Type
+     *
+     * @param  string $frontendInput
+     * @return void
+     * @throws \Magento\Framework\Exception\InputException
+     */
+    protected function validateFrontendInput($frontendInput)
+    {
+        $validator = $this->inputtypeValidatorFactory->create();
+        if (!$validator->isValid($frontendInput)) {
+            throw InputException::invalidFieldValue('frontend_input', $frontendInput);
+        }
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php
new file mode 100644
index 00000000000..1458c40ca53
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+/**
+ * Class WriteServiceInterface
+ * @package Magento\Catalog\Service\V1\Product\Attribute
+ */
+interface WriteServiceInterface
+{
+    /**
+     * Create attribute from data
+     *
+     * @param \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attributeMetadata
+     * @return string
+     * @throws \Magento\Framework\Exception\InputException
+     * @throws \Magento\Eav\Exception from validate()
+     */
+    public function create(\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attributeMetadata);
+
+    /**
+     * Update product attribute process
+     *
+     * @param  string $id
+     * @param  \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attribute
+     * @return string
+     * @throws \Magento\Framework\Exception\CouldNotSaveException
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function update($id, \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attribute);
+
+    /**
+     * Delete Attribute
+     *
+     * @param  string $attributeId
+     * @throws \Magento\Framework\Exception\NoSuchEntityException If ID is not found
+     * @throws \Exception If something goes wrong during delete
+     * @return bool True if the entity was deleted (always true)
+     */
+    public function remove($attributeId);
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Product/AttributeSet/ReadService.php b/app/code/Magento/Catalog/Service/V1/Product/AttributeSet/ReadService.php
index a5ffb524804..d74b2eeac80 100644
--- a/app/code/Magento/Catalog/Service/V1/Product/AttributeSet/ReadService.php
+++ b/app/code/Magento/Catalog/Service/V1/Product/AttributeSet/ReadService.php
@@ -145,6 +145,7 @@ class ReadService implements ReadServiceInterface
                 ->setDefaultValue($attribute->getDefaultValue())
                 ->setIsRequired((boolean)$attribute->getData('is_required'))
                 ->setIsUserDefined((boolean)$attribute->getData('is_user_defined'))
+                ->setFrontendInput($attribute->getData('frontend_input'))
                 ->create();
         }
         return $attributes;
diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php
deleted file mode 100644
index 27fd89b3490..00000000000
--- a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Catalog\Service\V1;
-
-use Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory;
-
-/**
- * Class ProductAttributeReadService
- * @package Magento\Catalog\Service\V1
- */
-class ProductAttributeReadService implements ProductAttributeReadServiceInterface
-{
-    /**
-     * @var ProductMetadataServiceInterface
-     */
-    private $metadataService;
-
-    /**
-     * @var \Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory
-     */
-    private $inputTypeFactory;
-
-    /**
-     * @var Data\ProductAttributeTypeBuilder
-     */
-    private $attributeTypeBuilder;
-
-    /**
-     * @param ProductMetadataServiceInterface $metadataService
-     * @param InputtypeFactory $inputTypeFactory
-     * @param Data\ProductAttributeTypeBuilder $attributeTypeBuilder
-     */
-    public function __construct(
-        ProductMetadataServiceInterface $metadataService,
-        InputtypeFactory $inputTypeFactory,
-        Data\ProductAttributeTypeBuilder $attributeTypeBuilder
-    ) {
-        $this->metadataService = $metadataService;
-        $this->inputTypeFactory = $inputTypeFactory;
-        $this->attributeTypeBuilder = $attributeTypeBuilder;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function types()
-    {
-        $types = [];
-        $inputType = $this->inputTypeFactory->create();
-
-        foreach ($inputType->toOptionArray() as $option) {
-            $types[] = $this->attributeTypeBuilder->populateWithArray($option)->create();
-        }
-        return $types;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function info($id)
-    {
-        return $this->metadataService->getAttributeMetadata(
-            ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
-            $id
-        );
-    }
-}
diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php
new file mode 100644
index 00000000000..81afa4f9a32
--- /dev/null
+++ b/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1;
+
+use Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory;
+
+/**
+ * Class ProductAttributeService
+ */
+class ProductAttributeService implements ProductAttributeServiceInterface
+{
+    /**
+     * @var ProductMetadataServiceInterface
+     */
+    private $metadataService;
+
+    /**
+     * @var \Magento\Eav\Model\Config
+     */
+    private $eavConfig;
+
+    /** @var  \Magento\Eav\Model\Resource\Entity\Attribute\Option\CollectionFactory */
+    private $optionCollectionFactory;
+
+    /**
+     * @param ProductMetadataServiceInterface $metadataService
+     * @param \Magento\Eav\Model\Config $eavConfig
+     * @param \Magento\Eav\Model\Resource\Entity\Attribute\Option\CollectionFactory $optionCollectionFactory
+     */
+    public function __construct(
+        ProductMetadataServiceInterface $metadataService,
+        \Magento\Eav\Model\Config $eavConfig,
+        \Magento\Eav\Model\Resource\Entity\Attribute\Option\CollectionFactory $optionCollectionFactory
+    ) {
+        $this->metadataService = $metadataService;
+        $this->eavConfig = $eavConfig;
+        $this->optionCollectionFactory = $optionCollectionFactory;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function options($id)
+    {
+        return $this->metadataService->getAttributeMetadata(
+            ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+            $id
+        )->getOptions();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addOption($id, \Magento\Catalog\Service\V1\Data\Eav\Option $option)
+    {
+        $model = $this->eavConfig->getAttribute(
+            \Magento\Catalog\Service\V1\ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+            $id
+        );
+        if (!$model) {
+            throw new \Magento\Framework\Exception\StateException('Attribute does no exist');
+        }
+
+        if (!$model->usesSource()) {
+            throw new \Magento\Framework\Exception\StateException('Attribute doesn\'t have any option');
+        }
+
+        $key = 'new_option';
+
+        $options = [];
+        $options['value'][$key][0] = $option->getLabel();
+        $options['order'][$key] = $option->getOrder();
+
+        if (is_array($option->getStoreLabels())) {
+            foreach ($option->getStoreLabels() as $label) {
+                $options['value'][$key][$label->getStoreId()] = $label->getLabel();
+            }
+        }
+
+        if ($option->isDefault()) {
+            $model->setDefault([$key]);
+        }
+
+        $model->setOption($options);
+        $model->save();
+        return true;
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php
similarity index 70%
rename from app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php
rename to app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php
index 7a1717db1cf..e4d5e1b0eab 100644
--- a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php
+++ b/app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php
@@ -26,25 +26,26 @@ namespace Magento\Catalog\Service\V1;
 use Magento\Catalog\Service\V1\Data\ProductAttributeType;
 
 /**
- * Class ProductAttributeReadServiceInterface
- * @package Magento\Catalog\Service\V1
+ * Class ProductAttributeServiceInterface
  */
-interface ProductAttributeReadServiceInterface
+interface ProductAttributeServiceInterface
 {
     /**
-     * Retrieve list of product attribute types
+     * Retrieve list of attribute options
      *
-     * @return \Magento\Catalog\Service\V1\Data\ProductAttributeType[]
+     * @param string $id
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Option[]
+     *
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
      */
-    public function types();
+    public function options($id);
 
     /**
-     * Get full information about a required attribute with the list of options
+     * Add option to attribute
      *
-     * @param  string $id
-     * @return \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata
-     *
-     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     * @param string $id
+     * @param \Magento\Catalog\Service\V1\Data\Eav\Option $option
+     * @return bool
      */
-    public function info($id);
+    public function addOption($id, \Magento\Catalog\Service\V1\Data\Eav\Option $option);
 }
diff --git a/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php b/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php
index 979a89caeec..8f2e5201bb7 100644
--- a/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php
+++ b/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php
@@ -26,6 +26,7 @@ namespace Magento\Catalog\Service\V1;
 use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
 use Magento\Framework\Exception\NoSuchEntityException;
 use Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata;
+use Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel;
 
 /**
  * Class ProductMetadataService
@@ -43,16 +44,6 @@ class ProductMetadataService implements ProductMetadataServiceInterface
      */
     private $scopeResolver;
 
-    /**
-     * @var Data\Eav\OptionBuilder
-     */
-    private $optionBuilder;
-
-    /**
-     * @var Data\Eav\ValidationRuleBuilder
-     */
-    private $validationRuleBuilder;
-
     /**
      * @var Data\Eav\AttributeMetadataBuilder
      */
@@ -61,21 +52,15 @@ class ProductMetadataService implements ProductMetadataServiceInterface
     /**
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver
-     * @param Data\Eav\OptionBuilder $optionBuilder
-     * @param Data\Eav\ValidationRuleBuilder $validationRuleBuilder
      * @param Data\Eav\AttributeMetadataBuilder $attributeMetadataBuilder
      */
     public function __construct(
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\App\ScopeResolverInterface $scopeResolver,
-        Data\Eav\OptionBuilder $optionBuilder,
-        Data\Eav\ValidationRuleBuilder $validationRuleBuilder,
         Data\Eav\AttributeMetadataBuilder $attributeMetadataBuilder
     ) {
         $this->eavConfig = $eavConfig;
         $this->scopeResolver = $scopeResolver;
-        $this->optionBuilder = $optionBuilder;
-        $this->validationRuleBuilder = $validationRuleBuilder;
         $this->attributeMetadataBuilder = $attributeMetadataBuilder;
     }
 
@@ -159,18 +144,16 @@ class ProductMetadataService implements ProductMetadataServiceInterface
         $data[AttributeMetadata::SCOPE] = $attribute->isScopeGlobal()
             ? 'global' : ($attribute->isScopeWebsite() ? 'website' : 'store');
 
-        // fill frontend labels
-        $data[AttributeMetadata::FRONTEND_LABEL] = array(
-            array(
-                'store_id' => 0,
-                'label' => $attribute->getFrontendLabel()
-            )
+        $data[AttributeMetadata::FRONTEND_LABEL] = [];
+        $data[AttributeMetadata::FRONTEND_LABEL][0] = array(
+            FrontendLabel::STORE_ID => 0,
+            FrontendLabel::LABEL => $attribute->getFrontendLabel()
         );
         if (is_array($attribute->getStoreLabels())) {
             foreach ($attribute->getStoreLabels() as $storeId => $label) {
-                $data[AttributeMetadata::FRONTEND_LABEL][] = array(
-                    'store_id' => $storeId,
-                    'label' => $label
+                $data[AttributeMetadata::FRONTEND_LABEL][$storeId] = array(
+                    FrontendLabel::STORE_ID => $storeId,
+                    FrontendLabel::LABEL => $label
                 );
             }
         }
diff --git a/app/code/Magento/Catalog/Service/V1/ProductService.php b/app/code/Magento/Catalog/Service/V1/ProductService.php
index ff88e63a3df..2e3b28eeeb0 100644
--- a/app/code/Magento/Catalog/Service/V1/ProductService.php
+++ b/app/code/Magento/Catalog/Service/V1/ProductService.php
@@ -74,7 +74,7 @@ class ProductService implements ProductServiceInterface
     private $converter;
 
     /**
-     * @var Data\SearchResultsBuilder
+     * @var \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder
      */
     private $searchResultsBuilder;
 
@@ -86,7 +86,7 @@ class ProductService implements ProductServiceInterface
      * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollection
      * @param ProductMetadataServiceInterface $metadataService
      * @param \Magento\Catalog\Service\V1\Data\Converter $converter
-     * @param Data\SearchResultsBuilder $searchResultsBuilder
+     * @param \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder $searchResultsBuilder
      */
     public function __construct(
         Product\Initialization\Helper $initializationHelper,
@@ -96,7 +96,7 @@ class ProductService implements ProductServiceInterface
         \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollection,
         ProductMetadataServiceInterface $metadataService,
         \Magento\Catalog\Service\V1\Data\Converter $converter,
-        Data\SearchResultsBuilder $searchResultsBuilder
+        \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder $searchResultsBuilder
     ) {
         $this->initializationHelper = $initializationHelper;
         $this->productMapper = $productMapper;
diff --git a/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php b/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php
index 02d4ca463a4..5d44ee353e3 100644
--- a/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php
+++ b/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php
@@ -72,10 +72,10 @@ interface ProductServiceInterface
     public function update($id, \Magento\Catalog\Service\V1\Data\Product $product);
 
     /**
-     * get product list product
+     * Get product list
      *
      * @param \Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria
-     * @return \Magento\Catalog\Service\V1\Data\SearchResults containing Data\Product objects
+     * @return \Magento\Catalog\Service\V1\Data\Product\SearchResults containing Data\Product objects
      */
     public function search(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria);
 }
diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index e38c660f426..a7f281199ba 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -26,7 +26,9 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
     <preference for="Magento\Catalog\Service\V1\ProductMetadataServiceInterface" type="Magento\Catalog\Service\V1\ProductMetadataService" />
     <preference for="Magento\Catalog\Service\V1\ProductServiceInterface" type="Magento\Catalog\Service\V1\ProductService" />
-    <preference for="Magento\Catalog\Service\V1\ProductAttributeReadServiceInterface" type="Magento\Catalog\Service\V1\ProductAttributeReadService" />
+    <preference for="Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface" type="Magento\Catalog\Service\V1\Product\Attribute\ReadService" />
+    <preference for="Magento\Catalog\Service\V1\Product\Attribute\WriteServiceInterface" type="Magento\Catalog\Service\V1\Product\Attribute\WriteService" />
+    <preference for="Magento\Catalog\Service\V1\ProductAttributeServiceInterface" type="Magento\Catalog\Service\V1\ProductAttributeService" />
     <preference for="Magento\Catalog\Model\ProductTypes\ConfigInterface" type="Magento\Catalog\Model\ProductTypes\Config" />
     <preference for="Magento\Catalog\Model\ProductOptions\ConfigInterface" type="Magento\Catalog\Model\ProductOptions\Config" />
     <preference for="Magento\Catalog\Model\Product\PriceModifierInterface" type="Magento\Catalog\Model\Product\PriceModifier\Composite" />
@@ -222,10 +224,6 @@
             <argument name="indexer" xsi:type="object" shared="false">Magento\Indexer\Model\IndexerInterface</argument>
         </arguments>
     </type>
-    <type name="Magento\ImportExport\Model\Import">
-        <plugin name="catalogProductFlatIndexerImport" type="\Magento\Catalog\Model\Indexer\Product\Flat\Plugin\Import" />
-        <plugin name="invalidatePriceIndexerOnImport" type="\Magento\Catalog\Model\Indexer\Product\Price\Plugin\Import" />
-    </type>
     <type name="Magento\CatalogRule\Model\Rule">
         <plugin name="reindexPriceOnRuleApply" type="\Magento\Catalog\Model\Indexer\Product\Price\Plugin\CatalogRule" />
     </type>
diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml
index 32387b3f840..dbd9e2cec08 100644
--- a/app/code/Magento/Catalog/etc/module.xml
+++ b/app/code/Magento/Catalog/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Catalog" version="1.6.0.0.26" active="true">
+    <module name="Magento_Catalog" schema_version="1.6.0.0.26" active="true">
         <sequence>
             <module name="Magento_Eav"/>
             <module name="Magento_Cms"/>
@@ -48,7 +48,6 @@
             <module name="Magento_Wishlist"/>
             <module name="Magento_Tax"/>
             <module name="Magento_Bundle"/>
-            <module name="Magento_ImportExport"/>
             <module name="Magento_CatalogInventory"/>
             <module name="Magento_Directory"/>
             <module name="Magento_CatalogRule"/>
diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml
index aa3c9ec05ca..68c16392095 100644
--- a/app/code/Magento/Catalog/etc/webapi.xml
+++ b/app/code/Magento/Catalog/etc/webapi.xml
@@ -56,13 +56,37 @@
         </resources>
     </route>
     <route url="/V1/products/attributes/types" method="GET">
-        <service class="Magento\Catalog\Service\V1\ProductAttributeReadServiceInterface" method="types"/>
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface" method="types"/>
         <resources>
             <resource ref="Magento_Catalog::attributes_attributes" />
         </resources>
     </route>
     <route url="/V1/products/attributes/:id" method="GET">
-        <service class="Magento\Catalog\Service\V1\ProductAttributeReadServiceInterface" method="info"/>
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface" method="info"/>
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
+    <route url="/V1/products/attributes" method="POST">
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\WriteServiceInterface" method="create"/>
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
+    <route url="/V1/products/attributes/:id" method="PUT">
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\WriteServiceInterface" method="update"/>
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
+    <route url="/V1/products/attributes/:attributeId" method="DELETE">
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\WriteServiceInterface" method="remove"/>
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
+    <route url="/V1/products/attributes" method="GET">
+        <service class="Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface" method="search"/>
         <resources>
             <resource ref="Magento_Catalog::attributes_attributes" />
         </resources>
@@ -181,6 +205,18 @@
             <resource ref="Magento_Catalog::catalog"/>
         </resources>
     </route>
+    <route url="/V1/products/attributes/:id/options" method="GET">
+        <service class="Magento\Catalog\Service\V1\ProductAttributeServiceInterface" method="options"/>
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
+    <route url="/V1/products/attributes/:id/options" method="POST">
+        <service class="Magento\Catalog\Service\V1\ProductAttributeServiceInterface" method="addOption" />
+        <resources>
+            <resource ref="Magento_Catalog::attributes_attributes" />
+        </resources>
+    </route>
     <route url="/V1/products/media/types/:attributeSetId" method="GET">
         <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\ReadServiceInterface" method="types"/>
         <resources>
diff --git a/app/code/Magento/Catalog/i18n/de_DE.csv b/app/code/Magento/Catalog/i18n/de_DE.csv
index 1ab046da2d9..500edd14173 100644
--- a/app/code/Magento/Catalog/i18n/de_DE.csv
+++ b/app/code/Magento/Catalog/i18n/de_DE.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","Anzahlzunahme aktivieren"
 "Enable WYSIWYG","WYSIWYG aktivieren"
 "Enabled","Aktiviert"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType sein"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType sein"
 "Error during retrieval of option value: %s","Fehler bei Abfragen von Optionswert: %s"
 "Exclude","Auschließen"
 "Expand All","Alle erweitern"
diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv
index 73557c01ae2..8fb4e90e6c5 100644
--- a/app/code/Magento/Catalog/i18n/en_US.csv
+++ b/app/code/Magento/Catalog/i18n/en_US.csv
@@ -270,6 +270,8 @@
 "Enable Quantity Increments","Enable Quantity Increments"
 "Enable WYSIWYG","Enable WYSIWYG"
 "Enabled","Enabled"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType"
 "Error during retrieval of option value: %s","Error during retrieval of option value: %s"
 "Exclude","Exclude"
 "Expand All","Expand All"
diff --git a/app/code/Magento/Catalog/i18n/es_ES.csv b/app/code/Magento/Catalog/i18n/es_ES.csv
index 9ea8012442d..7978c1de1e2 100644
--- a/app/code/Magento/Catalog/i18n/es_ES.csv
+++ b/app/code/Magento/Catalog/i18n/es_ES.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","Posibilitar Incrementos de Cantidad"
 "Enable WYSIWYG","Habilitar WYSIWYG"
 "Enabled","Habilitado"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType"
 "Error during retrieval of option value: %s","Error al recuperar el valor de la opción: %s"
 "Exclude","Excluir"
 "Expand All","Expandir todo"
diff --git a/app/code/Magento/Catalog/i18n/fr_FR.csv b/app/code/Magento/Catalog/i18n/fr_FR.csv
index b1eee5ea791..ccbe17f0aa1 100644
--- a/app/code/Magento/Catalog/i18n/fr_FR.csv
+++ b/app/code/Magento/Catalog/i18n/fr_FR.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","Activer quantité"
 "Enable WYSIWYG","Permettre WYSIWYG"
 "Enabled","Activé"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType"
 "Error during retrieval of option value: %s","Erreur lors de la récupération de la valeur de l'option:% s"
 "Exclude","Exclure"
 "Expand All","Tout développer"
diff --git a/app/code/Magento/Catalog/i18n/nl_NL.csv b/app/code/Magento/Catalog/i18n/nl_NL.csv
index 3bba923d85b..c2249b5662d 100644
--- a/app/code/Magento/Catalog/i18n/nl_NL.csv
+++ b/app/code/Magento/Catalog/i18n/nl_NL.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","Sta Quantity Incrementen toe"
 "Enable WYSIWYG","Sta WYSIWYG toe"
 "Enabled","Aan"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType"
 "Error during retrieval of option value: %s","Fout bij het ophalen van optie waarde: %s"
 "Exclude","Sluit Uit"
 "Expand All","Klap Alles Uit"
diff --git a/app/code/Magento/Catalog/i18n/pt_BR.csv b/app/code/Magento/Catalog/i18n/pt_BR.csv
index ff867c22e0a..967d22f0d00 100644
--- a/app/code/Magento/Catalog/i18n/pt_BR.csv
+++ b/app/code/Magento/Catalog/i18n/pt_BR.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","Habilitar Incrementos na Qtde."
 "Enable WYSIWYG","Habilitar WYSIWYG"
 "Enabled","Ativado"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType"
 "Error during retrieval of option value: %s","Erro ao recuperar valor de opção: %s"
 "Exclude","Excluir"
 "Expand All","Expandir Todos"
diff --git a/app/code/Magento/Catalog/i18n/zh_CN.csv b/app/code/Magento/Catalog/i18n/zh_CN.csv
index 79ac27d8357..02cb740b1d8 100644
--- a/app/code/Magento/Catalog/i18n/zh_CN.csv
+++ b/app/code/Magento/Catalog/i18n/zh_CN.csv
@@ -269,6 +269,8 @@
 "Enable Quantity Increments","启用数量增量"
 "Enable WYSIWYG","启用所见即所得"
 "Enabled","已启用"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","实体类型模块必须为\Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType的实例"
+"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","实体类型模块必须为\Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType的实例"
 "Error during retrieval of option value: %s","获取选项值 %s的过程中出错"
 "Exclude","排除"
 "Expand All","全部展开"
diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
similarity index 98%
rename from app/code/Magento/ImportExport/Model/Export/Entity/Product.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product.php
index e42ee802051..2e4f8fc812f 100644
--- a/app/code/Magento/ImportExport/Model/Export/Entity/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity;
+namespace Magento\CatalogImportExport\Model\Export;
 
 /**
  * Export entity product model
@@ -196,7 +196,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
     protected $_attributeColFactory;
 
     /**
-     * @var \Magento\ImportExport\Model\Export\Entity\Product\Type\Factory
+     * @var \Magento\CatalogImportExport\Model\Export\Product\Type\Factory
      */
     protected $_typeFactory;
 
@@ -208,7 +208,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
     protected $_linkTypeProvider;
 
     /**
-     * @var \Magento\ImportExport\Model\Export\RowCustomizerInterface
+     * @var \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface
      */
     protected $rowCustomizer;
 
@@ -228,7 +228,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
      * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeColFactory
      * @param Product\Type\Factory $_typeFactory
      * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider
-     * @param \Magento\ImportExport\Model\Export\RowCustomizerInterface $rowCustomizer
+     * @param \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer
      */
     public function __construct(
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
@@ -244,9 +244,9 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
         \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $itemFactory,
         \Magento\Catalog\Model\Resource\Product\Option\CollectionFactory $optionColFactory,
         \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeColFactory,
-        \Magento\ImportExport\Model\Export\Entity\Product\Type\Factory $_typeFactory,
+        \Magento\CatalogImportExport\Model\Export\Product\Type\Factory $_typeFactory,
         \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider,
-        \Magento\ImportExport\Model\Export\RowCustomizerInterface $rowCustomizer
+        \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer
     ) {
         $this->_entityCollection = $collection;
         $this->_exportConfig = $exportConfig;
@@ -320,16 +320,16 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
      */
     protected function _initTypeModels()
     {
-        $productTypes = $this->_exportConfig->getProductTypes();
+        $productTypes = $this->_exportConfig->getEntityTypes($this->getEntityTypeCode());
         foreach ($productTypes as $productTypeName => $productTypeConfig) {
             if (!($model = $this->_typeFactory->create($productTypeConfig['model']))) {
                 throw new \Magento\Framework\Model\Exception("Entity type model '{$productTypeConfig['model']}' is not found");
             }
-            if (!$model instanceof \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType) {
+            if (!$model instanceof \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType) {
                 throw new \Magento\Framework\Model\Exception(
                     __(
                         'Entity type model must be an instance of'
-                        . ' \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType'
+                        . ' \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType'
                     )
                 );
             }
diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php
similarity index 97%
rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php
index 07610b487fd..1864bbf7f9d 100644
--- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Export\Product\Type;
 
 use Magento\Catalog\Model\Resource\Eav\Attribute;
 
diff --git a/app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php
similarity index 84%
rename from app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php
index 52cf67e7050..290a8019075 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php
@@ -21,8 +21,8 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ConfigurableProduct\Model\Export\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Export\Product\Type;
 
-class Configurable extends \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType
+class Configurable extends \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType
 {
 }
diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php
similarity index 92%
rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php
index aaa6ff1fb60..40ad5f678cc 100644
--- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php
@@ -25,7 +25,7 @@
 /**
  * Export product type factory
  */
-namespace Magento\ImportExport\Model\Export\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Export\Product\Type;
 
 class Factory
 {
@@ -46,7 +46,7 @@ class Factory
 
     /**
      * @param string $className
-     * @return \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType
      * @throws \InvalidArgumentException
      */
     public function create($className)
diff --git a/app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php
similarity index 87%
rename from app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php
index 89939d3e6df..feda0988b48 100644
--- a/app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php
@@ -23,9 +23,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\GroupedProduct\Model\Export\Entity\Product\Type;
-
-use Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType;
+namespace Magento\CatalogImportExport\Model\Export\Product\Type;
 
 class Grouped extends AbstractType
 {
diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php
similarity index 93%
rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php
rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php
index b267fa29181..9482fa028e2 100644
--- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php
@@ -21,14 +21,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Export\Product\Type;
 
 /**
  * Export entity product type simple model
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Simple extends \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType
+class Simple extends \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType
 {
     /**
      * Overridden attributes parameters.
diff --git a/app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php
similarity index 97%
rename from app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php
rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php
index b7b7846c343..97db1a13b3c 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php
@@ -21,9 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ConfigurableProduct\Model\Export;
-
-use Magento\ImportExport\Model\Export\RowCustomizerInterface;
+namespace Magento\CatalogImportExport\Model\Export;
 
 class RowCustomizer implements RowCustomizerInterface
 {
diff --git a/app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php
similarity index 95%
rename from app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php
rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php
index 626698d74d8..d1e93ffcaa6 100644
--- a/app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\RowCustomizer;
+namespace Magento\CatalogImportExport\Model\Export\RowCustomizer;
 
-use Magento\ImportExport\Model\Export\RowCustomizerInterface;
+use Magento\CatalogImportExport\Model\Export\RowCustomizerInterface;
 use Magento\Framework\ObjectManager;
 
 class Composite implements RowCustomizerInterface
diff --git a/app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php
similarity index 97%
rename from app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php
rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php
index 6aaf6a0a88b..18231f0e29c 100644
--- a/app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export;
+namespace Magento\CatalogImportExport\Model\Export;
 
 /**
  * Interface RowCustomizerInterface
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
similarity index 97%
rename from app/code/Magento/ImportExport/Model/Import/Entity/Product.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product.php
index c3df73de556..a8607a1a938 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity;
+namespace Magento\CatalogImportExport\Model\Import;
 
 /**
  * Import entity product model
@@ -341,14 +341,14 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     /**
      * Media files uploader
      *
-     * @var \Magento\ImportExport\Model\Import\Uploader
+     * @var \Magento\CatalogImportExport\Model\Import\Uploader
      */
     protected $_fileUploader;
 
     /**
      * Import entity which provide import of product custom options
      *
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\Option
+     * @var \Magento\CatalogImportExport\Model\Import\Product\Option
      */
     protected $_optionEntity;
 
@@ -377,7 +377,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     protected $_importConfig;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory
+     * @var \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory
      */
     protected $_resourceFactory;
 
@@ -407,7 +407,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     protected $_storeManager;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\Type\Factory
+     * @var \Magento\CatalogImportExport\Model\Import\Product\Type\Factory
      */
     protected $_productTypeFactory;
 
@@ -417,12 +417,12 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     protected $_linkFactory;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Proxy\ProductFactory
+     * @var \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory
      */
     protected $_proxyProdFactory;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\UploaderFactory
+     * @var \Magento\CatalogImportExport\Model\Import\UploaderFactory
      */
     protected $_uploaderFactory;
 
@@ -473,17 +473,17 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      * @param \Magento\CatalogInventory\Service\V1\StockItem $stockItemService
      * @param \Magento\Catalog\Helper\Data $catalogData
      * @param \Magento\ImportExport\Model\Import\Config $importConfig
-     * @param \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory
-     * @param Product\OptionFactory $optionFactory
+     * @param \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory
+     * @param \Magento\CatalogImportExport\Model\Import\Product\OptionFactory $optionFactory
      * @param \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $setColFactory
      * @param \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory
      * @param \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService
      * @param \Magento\Catalog\Model\ProductFactory $productFactory
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param Product\Type\Factory $productTypeFactory
+     * @param \Magento\CatalogImportExport\Model\Import\Product\Type\Factory $productTypeFactory
      * @param \Magento\Catalog\Model\Resource\Product\LinkFactory $linkFactory
-     * @param \Magento\ImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory
-     * @param \Magento\ImportExport\Model\Import\UploaderFactory $uploaderFactory
+     * @param \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory
+     * @param \Magento\CatalogImportExport\Model\Import\UploaderFactory $uploaderFactory
      * @param \Magento\Framework\App\Filesystem $filesystem
      * @param \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac
      * @param \Magento\CatalogInventory\Model\Stock\ItemFactory $stockItemFactory
@@ -504,17 +504,17 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
         \Magento\CatalogInventory\Service\V1\StockItem $stockItemService,
         \Magento\Catalog\Helper\Data $catalogData,
         \Magento\ImportExport\Model\Import\Config $importConfig,
-        \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory,
-        \Magento\ImportExport\Model\Import\Entity\Product\OptionFactory $optionFactory,
+        \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory,
+        \Magento\CatalogImportExport\Model\Import\Product\OptionFactory $optionFactory,
         \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $setColFactory,
         \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory,
         \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService,
         \Magento\Catalog\Model\ProductFactory $productFactory,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
-        \Magento\ImportExport\Model\Import\Entity\Product\Type\Factory $productTypeFactory,
+        \Magento\CatalogImportExport\Model\Import\Product\Type\Factory $productTypeFactory,
         \Magento\Catalog\Model\Resource\Product\LinkFactory $linkFactory,
-        \Magento\ImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory,
-        \Magento\ImportExport\Model\Import\UploaderFactory $uploaderFactory,
+        \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory,
+        \Magento\CatalogImportExport\Model\Import\UploaderFactory $uploaderFactory,
         \Magento\Framework\App\Filesystem $filesystem,
         \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac,
         \Magento\CatalogInventory\Model\Stock\ItemFactory $stockItemFactory,
@@ -562,7 +562,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     /**
      * Retrieve instance of product custom options import entity
      *
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Option
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Option
      */
     public function getOptionEntity()
     {
@@ -736,7 +736,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      */
     protected function _initTypeModels()
     {
-        $productTypes = $this->_importConfig->getProductTypes();
+        $productTypes = $this->_importConfig->getEntityTypes($this->getEntityTypeCode());
         foreach ($productTypes as $productTypeName => $productTypeConfig) {
             $params = array($this, $productTypeName);
             if (!($model = $this->_productTypeFactory->create($productTypeConfig['model'], array('params' => $params)))
@@ -745,11 +745,11 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
                     sprintf("Entity type model '%s' is not found", $productTypeConfig['model'])
                 );
             }
-            if (!$model instanceof \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType) {
+            if (!$model instanceof \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType) {
                 throw new \Magento\Framework\Model\Exception(
                     __(
                         'Entity type model must be an instance of ' .
-                        'Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType'
+                        'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType'
                     )
                 );
             }
@@ -1246,7 +1246,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
      */
     protected function _saveProducts()
     {
-        /** @var $resource \Magento\ImportExport\Model\Import\Proxy\Product\Resource */
+        /** @var $resource \Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource */
         $resource = $this->_resourceFactory->create();
         $priceIsGlobal = $this->_catalogData->isPriceGlobal();
         $productLimit = null;
@@ -1549,7 +1549,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     /**
      * Returns an object for upload a media files
      *
-     * @return \Magento\ImportExport\Model\Import\Uploader
+     * @return \Magento\CatalogImportExport\Model\Import\Uploader
      * @throws \Magento\Framework\Model\Exception
      */
     protected function _getUploader()
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
similarity index 99%
rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
index 161b84e0650..976c73d7c77 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product;
+namespace Magento\CatalogImportExport\Model\Import\Product;
 
 /**
  * Entity class which provide possibility to import product custom options
@@ -187,7 +187,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
     /**
      * Parent import product entity
      *
-     * @var \Magento\ImportExport\Model\Import\Entity\Product
+     * @var \Magento\CatalogImportExport\Model\Import\Product
      */
     protected $_productEntity;
 
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php
similarity index 94%
rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php
index 720026151ab..10901d740ab 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 /**
  * Import entity abstract product type model
@@ -78,7 +78,7 @@ abstract class AbstractType
     /**
      * Product entity object.
      *
-     * @var \Magento\ImportExport\Model\Import\Entity\Product
+     * @var \Magento\CatalogImportExport\Model\Import\Product
      */
     protected $_entityModel;
 
@@ -120,7 +120,7 @@ abstract class AbstractType
                 $params[1]
             ) || !is_object(
                 $params[0]
-            ) || !$params[0] instanceof \Magento\ImportExport\Model\Import\Entity\Product
+            ) || !$params[0] instanceof \Magento\CatalogImportExport\Model\Import\Product
             ) {
                 throw new \Magento\Framework\Model\Exception(__('Please correct the parameters.'));
             }
@@ -140,7 +140,7 @@ abstract class AbstractType
      * @param string $attrSetName Name of attribute set.
      * @param array $attrParams Refined attribute parameters.
      * @param mixed $attribute
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      */
     protected function _addAttributeParams($attrSetName, array $attrParams, $attribute)
     {
@@ -159,7 +159,7 @@ abstract class AbstractType
     protected function _getProductAttributes($attrSetData)
     {
         if (is_array($attrSetData)) {
-            return $this->_attributes[$attrSetData[\Magento\ImportExport\Model\Import\Entity\Product::COL_ATTR_SET]];
+            return $this->_attributes[$attrSetData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET]];
         } else {
             return $this->_attributes[$attrSetData];
         }
@@ -272,7 +272,7 @@ abstract class AbstractType
         $error = false;
         $rowScope = $this->_entityModel->getRowScope($rowData);
 
-        if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_NULL != $rowScope) {
+        if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_NULL != $rowScope) {
             foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
                 // check value for non-empty in the case of required attribute?
                 if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) {
@@ -280,7 +280,7 @@ abstract class AbstractType
                 } elseif ($this->_isAttributeRequiredCheckNeeded($attrCode) && $attrParams['is_required']) {
                     // For the default scope - if this is a new product or
                     // for an old product, if the imported doc has the column present for the attrCode
-                    if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $rowScope &&
+                    if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $rowScope &&
                         ($isNewProduct ||
                         array_key_exists(
                             $attrCode,
@@ -288,7 +288,7 @@ abstract class AbstractType
                         ))
                     ) {
                         $this->_entityModel->addRowError(
-                            \Magento\ImportExport\Model\Import\Entity\Product::ERROR_VALUE_IS_REQUIRED,
+                            \Magento\CatalogImportExport\Model\Import\Product::ERROR_VALUE_IS_REQUIRED,
                             $rowNum,
                             $attrCode
                         );
diff --git a/app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php
similarity index 97%
rename from app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php
index b1ec11bc371..8baafce4c66 100644
--- a/app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php
@@ -23,9 +23,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ConfigurableProduct\Model\Import\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
-class Configurable extends \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
 {
     /**
      * Error codes.
@@ -178,7 +178,7 @@ class Configurable extends \Magento\ImportExport\Model\Import\Entity\Product\Typ
      * @param string $attrSetName Name of attribute set.
      * @param array $attrParams Refined attribute parameters.
      * @param mixed $attribute
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      */
     protected function _addAttributeParams($attrSetName, array $attrParams, $attribute)
     {
@@ -410,7 +410,7 @@ class Configurable extends \Magento\ImportExport\Model\Import\Entity\Product\Typ
      * Save product type specific data.
      *
      * @throws \Exception
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
@@ -450,8 +450,8 @@ class Configurable extends \Magento\ImportExport\Model\Import\Entity\Product\Typ
                 }
                 // remember SCOPE_DEFAULT row data
                 $scope = $this->_entityModel->getRowScope($rowData);
-                if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $scope) {
-                    $productData = $newSku[$rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_SKU]];
+                if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) {
+                    $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]];
 
                     if ($this->_type != $productData['type_id']) {
                         $productData = null;
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php
similarity index 93%
rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php
index 13863a2ae73..50c61076225 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 /**
  * Import product type factory
@@ -46,7 +46,7 @@ class Factory
     /**
      * @param string $className
      * @param array $arguments
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      * @throws \InvalidArgumentException
      */
     public function create($className, array $arguments = array())
diff --git a/app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php
similarity index 93%
rename from app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php
index f4a553a6217..7492697f6a7 100644
--- a/app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php
@@ -23,9 +23,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\GroupedProduct\Model\Import\Entity\Product\Type;
-
-use Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 class Grouped extends AbstractType
 {
@@ -96,7 +94,7 @@ class Grouped extends AbstractType
     /**
      * Save product type specific data.
      *
-     * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      *
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
@@ -149,16 +147,16 @@ class Grouped extends AbstractType
                     continue;
                 }
                 $scope = $this->_entityModel->getRowScope($rowData);
-                if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $scope) {
-                    $productData = $newSku[$rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_SKU]];
+                if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) {
+                    $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]];
                 } else {
-                    $colAttrSet = \Magento\ImportExport\Model\Import\Entity\Product::COL_ATTR_SET;
+                    $colAttrSet = \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET;
                     $rowData[$colAttrSet] = $productData['attr_set_code'];
-                    $rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_TYPE] = $productData['type_id'];
+                    $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] = $productData['type_id'];
                 }
                 $productId = $productData['entity_id'];
 
-                if ($this->_type != $rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_TYPE]) {
+                if ($this->_type != $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE]) {
                     continue;
                 }
                 $linksData['product_ids'][$productId] = true;
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php
similarity index 91%
rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php
index 53fa0169133..15ed63ce9ac 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php
@@ -21,14 +21,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 /**
  * Import entity simple product type
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-class Simple extends \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+class Simple extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
 {
     /**
      * Attributes' codes which will be allowed anyway, independently from its visibility property.
diff --git a/app/code/Magento/ImportExport/Model/Import/Proxy/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php
similarity index 95%
rename from app/code/Magento/ImportExport/Model/Import/Proxy/Product.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php
index b9f86ab1517..3588c755302 100644
--- a/app/code/Magento/ImportExport/Model/Import/Proxy/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php
@@ -27,7 +27,7 @@
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-namespace Magento\ImportExport\Model\Import\Proxy;
+namespace Magento\CatalogImportExport\Model\Import\Proxy;
 
 class Product extends \Magento\Catalog\Model\Product
 {
diff --git a/app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php
similarity index 95%
rename from app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php
index fb25a62fbb4..a701d312e29 100644
--- a/app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php
@@ -27,7 +27,7 @@
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-namespace Magento\ImportExport\Model\Import\Proxy\Product;
+namespace Magento\CatalogImportExport\Model\Import\Proxy\Product;
 
 class Resource extends \Magento\Catalog\Model\Resource\Product
 {
diff --git a/app/code/Magento/ImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php
similarity index 99%
rename from app/code/Magento/ImportExport/Model/Import/Uploader.php
rename to app/code/Magento/CatalogImportExport/Model/Import/Uploader.php
index e7ce134a3cd..04dc6c2090f 100644
--- a/app/code/Magento/ImportExport/Model/Import/Uploader.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import;
+namespace Magento\CatalogImportExport\Model\Import;
 
 /**
  * Import entity product model
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php
similarity index 96%
rename from app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php
rename to app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php
index 2813821c4e8..f411fa94d10 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php
+++ b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Model\Indexer\Product\Flat\Plugin;
+namespace Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin;
 
 class Import
 {
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
similarity index 88%
rename from app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php
rename to app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
index 68eba09acff..ad29f49e9d0 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php
+++ b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Model\Indexer\Product\Price\Plugin;
+namespace Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin;
 
-class Import extends AbstractPlugin
+class Import extends \Magento\Catalog\Model\Indexer\Product\Price\Plugin\AbstractPlugin
 {
     /**
      * After import handler
diff --git a/app/code/Magento/GroupedProduct/etc/export.xml b/app/code/Magento/CatalogImportExport/etc/config.xml
similarity index 85%
rename from app/code/Magento/GroupedProduct/etc/export.xml
rename to app/code/Magento/CatalogImportExport/etc/config.xml
index 9a6547bf3e9..7b8a9c1f6e7 100644
--- a/app/code/Magento/GroupedProduct/etc/export.xml
+++ b/app/code/Magento/CatalogImportExport/etc/config.xml
@@ -23,6 +23,9 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/export.xsd">
-    <productType name="grouped" model="Magento\GroupedProduct\Model\Export\Entity\Product\Type\Grouped" />
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd">
+    <default>
+        <export>
+        </export>
+    </default>
 </config>
diff --git a/app/code/Magento/CatalogImportExport/etc/di.xml b/app/code/Magento/CatalogImportExport/etc/di.xml
new file mode 100644
index 00000000000..3b23b8aa687
--- /dev/null
+++ b/app/code/Magento/CatalogImportExport/etc/di.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\CatalogImportExport\Model\Export\RowCustomizerInterface" type="Magento\CatalogImportExport\Model\Export\RowCustomizer\Composite" />
+    <type name="Magento\ImportExport\Model\Import">
+        <plugin name="catalogProductFlatIndexerImport" type="\Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin\Import" />
+        <plugin name="invalidatePriceIndexerOnImport" type="\Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin\Import" />
+    </type>
+    <type name="Magento\CatalogImportExport\Model\Export\RowCustomizer\Composite">
+        <arguments>
+            <argument name="customizers" xsi:type="array">
+                <item name="configurableProduct" xsi:type="string">Magento\CatalogImportExport\Model\Export\RowCustomizer</item>
+            </argument>
+        </arguments>
+    </type>
+</config>
diff --git a/app/code/Magento/ImportExport/etc/export.xml b/app/code/Magento/CatalogImportExport/etc/export.xml
similarity index 66%
rename from app/code/Magento/ImportExport/etc/export.xml
rename to app/code/Magento/CatalogImportExport/etc/export.xml
index ee9f966cb50..9d3fce872ca 100644
--- a/app/code/Magento/ImportExport/etc/export.xml
+++ b/app/code/Magento/CatalogImportExport/etc/export.xml
@@ -24,8 +24,10 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/export.xsd">
-    <entity name="catalog_product" label="Products" model="Magento\ImportExport\Model\Export\Entity\Product" />
-    <productType name="simple" model="Magento\ImportExport\Model\Export\Entity\Product\Type\Simple" />
-    <productType name="virtual" model="Magento\ImportExport\Model\Export\Entity\Product\Type\Simple" />
+    <entity name="catalog_product" label="Products" model="Magento\CatalogImportExport\Model\Export\Product" entityAttributeFilterType="catalog_product"/>
+    <entityType entity="catalog_product" name="simple" model="Magento\CatalogImportExport\Model\Export\Product\Type\Simple" />
+    <entityType entity="catalog_product" name="virtual" model="Magento\CatalogImportExport\Model\Export\Product\Type\Simple" />
+    <entityType entity="catalog_product" name="grouped" model="Magento\CatalogImportExport\Model\Export\Product\Type\Grouped" />
+    <entityType entity="catalog_product" name="configurable" model="Magento\CatalogImportExport\Model\Export\Product\Type\Configurable" />
     <fileFormat name="csv" label="CSV" model="Magento\ImportExport\Model\Export\Adapter\Csv" />
 </config>
diff --git a/app/code/Magento/ImportExport/etc/import.xml b/app/code/Magento/CatalogImportExport/etc/import.xml
similarity index 59%
rename from app/code/Magento/ImportExport/etc/import.xml
rename to app/code/Magento/CatalogImportExport/etc/import.xml
index a6052786aed..74324b3e3ba 100644
--- a/app/code/Magento/ImportExport/etc/import.xml
+++ b/app/code/Magento/CatalogImportExport/etc/import.xml
@@ -24,7 +24,12 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/import.xsd">
-    <entity name="catalog_product" label="Products" model="Magento\ImportExport\Model\Import\Entity\Product" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
-    <productType name="simple" model="Magento\ImportExport\Model\Import\Entity\Product\Type\Simple" />
-    <productType name="virtual" model="Magento\ImportExport\Model\Import\Entity\Product\Type\Simple" />
+    <entity name="catalog_product" label="Products" model="Magento\CatalogImportExport\Model\Import\Product" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
+    <entityType entity="catalog_product" name="simple" model="Magento\CatalogImportExport\Model\Import\Product\Type\Simple" />
+    <entityType entity="catalog_product" name="virtual" model="Magento\CatalogImportExport\Model\Import\Product\Type\Simple" />
+    <entityType entity="catalog_product" name="grouped" model="Magento\CatalogImportExport\Model\Import\Product\Type\Grouped" />
+    <entityType entity="catalog_product" name="configurable" model="Magento\CatalogImportExport\Model\Import\Product\Type\Configurable" />
+    <relatedIndexer entity="catalog_product" name="catalog_product_price" />
+    <relatedIndexer entity="catalog_product" name="catalogsearch_fulltext" />
+    <relatedIndexer entity="catalog_product" name="catalog_product_flat" />
 </config>
diff --git a/app/code/Magento/CatalogImportExport/etc/module.xml b/app/code/Magento/CatalogImportExport/etc/module.xml
new file mode 100644
index 00000000000..c770dde9d5e
--- /dev/null
+++ b/app/code/Magento/CatalogImportExport/etc/module.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_CatalogImportExport" schema_version="1.0.0.0" active="true">
+        <depends>
+            <module name="Magento_Core"/>
+            <module name="Magento_Catalog"/>
+            <module name="Magento_Eav"/>
+            <module name="Magento_ImportExport"/>
+            <module name="Magento_Store"/>
+            <module name="Magento_CatalogInventory"/>
+            <module name="Magento_Customer"/>
+            <module name="Magento_GroupedProduct"/>
+            <module name="Magento_ConfigurableProduct"/>
+        </depends>
+    </module>
+</config>
diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml
index 0ba165098ca..609eab35846 100644
--- a/app/code/Magento/CatalogInventory/etc/module.xml
+++ b/app/code/Magento/CatalogInventory/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_CatalogInventory" version="1.6.0.0.4" active="true">
+    <module name="Magento_CatalogInventory" schema_version="1.6.0.0.4" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml
index 944adad1f57..2951c5c618a 100644
--- a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml
+++ b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml
@@ -28,6 +28,7 @@
         <arguments>
             <argument name="relatedCacheTypes" xsi:type="array">
                 <item name="blockCache" xsi:type="string">block_html</item>
+                <item name="fullPageCache" xsi:type="string">full_page</item>
             </argument>
         </arguments>
     </type>
diff --git a/app/code/Magento/CatalogRule/etc/module.xml b/app/code/Magento/CatalogRule/etc/module.xml
index 4eb5a509cf0..da7cd1f9cc1 100644
--- a/app/code/Magento/CatalogRule/etc/module.xml
+++ b/app/code/Magento/CatalogRule/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_CatalogRule" version="1.6.0.4" active="true">
+    <module name="Magento_CatalogRule" schema_version="1.6.0.4" active="true">
         <sequence>
             <module name="Magento_Rule"/>
             <module name="Magento_Catalog"/>
diff --git a/app/code/Magento/CatalogSearch/Controller/Advanced.php b/app/code/Magento/CatalogSearch/Controller/Advanced.php
index effeaabf945..6b2cb3c8975 100644
--- a/app/code/Magento/CatalogSearch/Controller/Advanced.php
+++ b/app/code/Magento/CatalogSearch/Controller/Advanced.php
@@ -92,18 +92,16 @@ class Advanced extends \Magento\Framework\App\Action\Action
      */
     public function resultAction()
     {
-        $this->_view->loadLayout();
         try {
             $this->_catalogSearchAdvanced->addFilters($this->getRequest()->getQuery());
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
-            $defaultUrl = $this->_urlFactory->create()->addQueryParams(
-                $this->getRequest()->getQuery()
-            )->getUrl(
-                '*/*/'
-            );
+            $defaultUrl = $this->_urlFactory->create()
+                ->addQueryParams($this->getRequest()->getQuery())
+                ->getUrl('*/*/');
             $this->getResponse()->setRedirect($this->_redirect->error($defaultUrl));
         }
+        $this->_view->loadLayout();
         $this->_view->renderLayout();
     }
 }
diff --git a/app/code/Magento/CatalogSearch/Model/Advanced.php b/app/code/Magento/CatalogSearch/Model/Advanced.php
index 7c4329b46a3..13858842888 100644
--- a/app/code/Magento/CatalogSearch/Model/Advanced.php
+++ b/app/code/Magento/CatalogSearch/Model/Advanced.php
@@ -21,6 +21,23 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+namespace Magento\CatalogSearch\Model;
+
+use Magento\Catalog\Model\Config;
+use Magento\Catalog\Model\Product\Visibility;
+use Magento\Catalog\Model\ProductFactory;
+use Magento\Catalog\Model\Resource\Eav\Attribute;
+use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory;
+use Magento\CatalogSearch\Model\Resource\Advanced\Collection;
+use Magento\CatalogSearch\Model\Resource\EngineInterface;
+use Magento\CatalogSearch\Model\Resource\EngineProvider;
+use Magento\Framework\Model\Exception;
+use Magento\Framework\Model\Context;
+use Magento\Framework\Registry;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Directory\Model\Currency;
+use Magento\Directory\Model\CurrencyFactory;
+use Magento\Eav\Model\Entity\Attribute as EntityAttribute;
 
 /**
  * Catalog advanced search model
@@ -45,25 +62,6 @@
  *
  * @author      Magento Core Team <core@magentocommerce.com>
  */
-namespace Magento\CatalogSearch\Model;
-
-use Magento\Catalog\Model\Config;
-use Magento\Catalog\Model\Product\Visibility;
-use Magento\Catalog\Model\ProductFactory;
-use Magento\Catalog\Model\Resource\Eav\Attribute;
-use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory;
-use Magento\CatalogSearch\Helper\Data;
-use Magento\CatalogSearch\Model\Resource\Advanced\Collection;
-use Magento\CatalogSearch\Model\Resource\EngineInterface;
-use Magento\CatalogSearch\Model\Resource\EngineProvider;
-use Magento\Framework\Model\Exception;
-use Magento\Framework\Model\Context;
-use Magento\Framework\Registry;
-use Magento\Store\Model\StoreManagerInterface;
-use Magento\Directory\Model\Currency;
-use Magento\Directory\Model\CurrencyFactory;
-use Magento\Eav\Model\Entity\Attribute as EntityAttribute;
-
 class Advanced extends \Magento\Framework\Model\AbstractModel
 {
     /**
@@ -138,7 +136,6 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
      * @param Visibility $catalogProductVisibility
      * @param Config $catalogConfig
      * @param EngineProvider $engineProvider
-     * @param Data $helper
      * @param CurrencyFactory $currencyFactory
      * @param ProductFactory $productFactory
      * @param StoreManagerInterface $storeManager
@@ -151,7 +148,6 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
         Visibility $catalogProductVisibility,
         Config $catalogConfig,
         EngineProvider $engineProvider,
-        Data $helper,
         CurrencyFactory $currencyFactory,
         ProductFactory $productFactory,
         StoreManagerInterface $storeManager,
@@ -203,7 +199,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
      *
      * @param   array $values
      * @return  $this
-     * @throws \Magento\Framework\Model\Exception
+     * @throws Exception
      */
     public function addFilters($values)
     {
@@ -238,7 +234,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
                         $this->_addSearchCriteria($attribute, $value);
                     }
                 }
-            } else if ($attribute->isIndexable()) {
+            } elseif ($attribute->isIndexable()) {
                 if (!is_string($value) || strlen($value) != 0) {
                     if ($this->_getResource()->addIndexableAttributeModifiedFilter(
                         $this->getProductCollection(),
@@ -272,9 +268,10 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
             }
         }
         if ($allConditions) {
+            $this->_registry->register('advanced_search_conditions', $allConditions);
             $this->getProductCollection()->addFieldsToFilter($allConditions);
-        } else if (!$hasConditions) {
-            throw new \Magento\Framework\Model\Exception(__('Please specify at least one search term.'));
+        } elseif (!$hasConditions) {
+            throw new Exception(__('Please specify at least one search term.'));
         }
 
         return $this;
@@ -324,7 +321,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
         }
 
         if (($attribute->getFrontendInput() == 'select' ||
-            $attribute->getFrontendInput() == 'multiselect') && is_array($value)
+                $attribute->getFrontendInput() == 'multiselect') && is_array($value)
         ) {
             foreach ($value as $key => $val) {
                 $value[$key] = $attribute->getSource()->getOptionText($val);
@@ -334,7 +331,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
                 }
             }
             $value = implode(', ', $value);
-        } else if ($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') {
+        } elseif ($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') {
             $value = $attribute->getSource()->getOptionText($value);
             if (is_array($value)) {
                 $value = $value['label'];
@@ -386,13 +383,13 @@ class Advanced extends \Magento\Framework\Model\AbstractModel
      */
     public function prepareProductCollection($collection)
     {
-        $collection->addAttributeToSelect(
-            $this->_catalogConfig->getProductAttributes()
-        )->setStore(
-            $this->_storeManager->getStore()
-        )->addMinimalPrice()->addTaxPercents()->addStoreFilter()->setVisibility(
-            $this->_catalogProductVisibility->getVisibleInSearchIds()
-        );
+        $collection
+            ->addAttributeToSelect($this->_catalogConfig->getProductAttributes())
+            ->setStore($this->_storeManager->getStore())
+            ->addMinimalPrice()
+            ->addTaxPercents()
+            ->addStoreFilter()
+            ->setVisibility($this->_catalogProductVisibility->getVisibleInSearchIds());
 
         return $this;
     }
diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php
new file mode 100644
index 00000000000..831dbe38d7e
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model\Layer;
+
+use Magento\Catalog\Model\CategoryFactory;
+use Magento\Catalog\Model\Layer;
+use Magento\Catalog\Model\Resource;
+use Magento\Framework\Object;
+
+class Advanced extends \Magento\Catalog\Model\Layer
+{
+    /**
+     * @param Advanced\Context $context
+     * @param \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory
+     * @param CategoryFactory $categoryFactory
+     * @param Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory
+     * @param Resource\Product $catalogProduct
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Framework\Registry $registry
+     * @param array $data
+     */
+    public function __construct(
+        Advanced\Context $context,
+        \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory,
+        CategoryFactory $categoryFactory,
+        Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory,
+        Resource\Product $catalogProduct,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Framework\Registry $registry,
+        array $data = array()
+    ) {
+        parent::__construct(
+            $context,
+            $layerStateFactory,
+            $categoryFactory,
+            $attributeCollectionFactory,
+            $catalogProduct,
+            $storeManager,
+            $registry,
+            $data
+        );
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php
new file mode 100644
index 00000000000..b0d7f3173ae
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model\Layer\Advanced;
+
+use Magento\Catalog\Model\Layer\CollectionFilterInterface;
+
+class CollectionFilter implements CollectionFilterInterface
+{
+    /**
+     * @var \Magento\Catalog\Model\Config
+     */
+    protected $catalogConfig;
+
+    /**
+     * @var \Magento\CatalogSearch\Helper\Data
+     */
+    protected $helper;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Visibility
+     */
+    protected $productVisibility;
+
+    /**
+     * @param \Magento\Catalog\Model\Config $catalogConfig
+     * @param \Magento\CatalogSearch\Helper\Data $helper
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Catalog\Model\Product\Visibility $productVisibility
+     * @param \Magento\Framework\Registry $registry
+     */
+    public function __construct(
+        \Magento\Catalog\Model\Config $catalogConfig,
+        \Magento\CatalogSearch\Helper\Data $helper,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Catalog\Model\Product\Visibility $productVisibility,
+        \Magento\Framework\Registry $registry
+    ) {
+        $this->catalogConfig = $catalogConfig;
+        $this->helper = $helper;
+        $this->storeManager = $storeManager;
+        $this->productVisibility = $productVisibility;
+        $this->_registry = $registry;
+    }
+
+    /**
+     * @param \Magento\Catalog\Model\Resource\Product\Collection $collection
+     * @param \Magento\Catalog\Model\Category $category
+     * @return void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function filter(
+        $collection,
+        \Magento\Catalog\Model\Category $category
+    ) {
+        $collection
+            ->addAttributeToSelect($this->catalogConfig->getProductAttributes())
+            ->addFieldsToFilter($this->_registry->registry('advanced_search_conditions'))
+            ->setStore($this->storeManager->getStore())
+            ->addMinimalPrice()
+            ->addTaxPercents()
+            ->addStoreFilter()
+            ->setVisibility($this->productVisibility->getVisibleInSearchIds());
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php
new file mode 100644
index 00000000000..809ca9fd7c5
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model\Layer\Advanced;
+
+class Context extends \Magento\Catalog\Model\Layer\Context
+{
+    /**
+     * @param ItemCollectionProvider $collectionProvider
+     * @param \Magento\Catalog\Model\Layer\Search\StateKey $stateKey
+     * @param CollectionFilter $collectionFilter
+     */
+    public function __construct(
+        ItemCollectionProvider $collectionProvider,
+        \Magento\Catalog\Model\Layer\Search\StateKey $stateKey,
+        CollectionFilter $collectionFilter
+    ) {
+        parent::__construct($collectionProvider, $stateKey, $collectionFilter);
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/FilterableAttributeList.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/FilterableAttributeList.php
new file mode 100644
index 00000000000..d851bc4ba1e
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/FilterableAttributeList.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model\Layer\Advanced;
+
+
+class FilterableAttributeList extends \Magento\Catalog\Model\Layer\Category\FilterableAttributeList
+{
+    /**
+     * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $collectionFactory
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\CatalogSearch\Model\Layer\Advanced $layer
+     */
+    public function __construct(
+        \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $collectionFactory,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\CatalogSearch\Model\Layer\Advanced $layer
+    ) {
+        parent::__construct($collectionFactory, $storeManager, $layer);
+    }
+
+    /**
+     * @param \Magento\Catalog\Model\Resource\Product\Attribute\Collection $collection
+     * @return \Magento\Catalog\Model\Resource\Product\Attribute\Collection
+     */
+    protected function _prepareAttributeCollection($collection)
+    {
+        $collection->addDisplayInAdvancedSearchFilter()->addVisibleFilter();
+        return $collection;
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php
new file mode 100644
index 00000000000..41a23bb1ff8
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ *
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model\Layer\Advanced;
+
+use Magento\Catalog\Model\Layer\ItemCollectionProviderInterface;
+use Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory;
+
+class ItemCollectionProvider implements ItemCollectionProviderInterface
+{
+    /**
+     * @var CollectionFactory
+     */
+    protected $advancedCollectionFactory;
+
+    /**
+     * ItemCollectionProvider constructor
+     *
+     * @param CollectionFactory $fulltextCollectionFactory
+     */
+    public function __construct(CollectionFactory $fulltextCollectionFactory)
+    {
+        $this->advancedCollectionFactory = $fulltextCollectionFactory;
+    }
+
+    /**
+     * Retrieve item colleciton
+     *
+     * @param \Magento\Catalog\Model\Category $category
+     * @return \Magento\CatalogSearch\Model\Resource\Advanced\Collection
+     */
+    public function getCollection(\Magento\Catalog\Model\Category $category)
+    {
+        return $this->advancedCollectionFactory->create();
+    }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
index ee15a21acb2..d27a819b8db 100644
--- a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
+++ b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php
@@ -72,7 +72,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      * @param \Magento\Framework\Stdlib\DateTime $dateTime
      * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory
      * @param \Zend_Db_Adapter_Abstract $connection
-     * 
+     *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -134,6 +134,22 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
         return $this;
     }
 
+    /**
+     * Add backend search query filter (search by all stores)
+     *
+     * @param string $query
+     * @return $this
+     */
+    public function addBackendSearchFilter($query)
+    {
+        $this->_searchQuery = $query;
+        $this->addFieldToFilter(
+            'entity_id',
+            array('in' => new \Zend_Db_Expr($this->_getSearchEntityIdsSql($query, false)))
+        );
+        return $this;
+    }
+
     /**
      * Retrieve collection of all attributes
      *
@@ -192,9 +208,10 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
      * Retrieve SQL for search entities
      *
      * @param mixed $query
+     * @param bool $searchOnlyInCurrentStore Search only in current store or in all stores
      * @return string
      */
-    protected function _getSearchEntityIdsSql($query)
+    protected function _getSearchEntityIdsSql($query, $searchOnlyInCurrentStore = true)
     {
         $tables = array();
         $selects = array();
@@ -226,6 +243,15 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
             }
         }
 
+        if ($searchOnlyInCurrentStore) {
+            $joinCondition = $this->getConnection()->quoteInto(
+                't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = ?',
+                $this->getStoreId()
+            );
+        } else {
+            $joinCondition = 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id';
+        }
+
         $ifValueId = $this->getConnection()->getIfNullSql('t2.value', 't1.value');
         foreach ($tables as $table => $attributeIds) {
             $selects[] = $this->getConnection()->select()->from(
@@ -233,10 +259,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection
                 'entity_id'
             )->joinLeft(
                 array('t2' => $table),
-                $this->getConnection()->quoteInto(
-                    't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = ?',
-                    $this->getStoreId()
-                ),
+                $joinCondition,
                 array()
             )->where(
                 't1.attribute_id IN (?)',
diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml
index a58caa081c6..27957360307 100644
--- a/app/code/Magento/CatalogSearch/etc/di.xml
+++ b/app/code/Magento/CatalogSearch/etc/di.xml
@@ -31,4 +31,14 @@
             </argument>
         </arguments>
     </type>
+    <virtualType name="advancedSearchFilterList" type="Magento\Catalog\Model\Layer\FilterList">
+        <arguments>
+            <argument name="filterableAttributes" xsi:type="object">Magento\CatalogSearch\Model\Layer\Advanced\FilterableAttributeList</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\CatalogSearch\Model\Layer\Advanced\FilterableAttributeList">
+        <arguments>
+            <argument name="layer" xsi:type="object">Magento\CatalogSearch\Model\Layer\Advanced</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/CatalogSearch/etc/module.xml b/app/code/Magento/CatalogSearch/etc/module.xml
index 15534ff9c5c..b796f63bc82 100644
--- a/app/code/Magento/CatalogSearch/etc/module.xml
+++ b/app/code/Magento/CatalogSearch/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_CatalogSearch" version="1.6.0.0" active="true">
+    <module name="Magento_CatalogSearch" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/Centinel/etc/module.xml b/app/code/Magento/Centinel/etc/module.xml
index 932a47ea503..68c17c36957 100644
--- a/app/code/Magento/Centinel/etc/module.xml
+++ b/app/code/Magento/Centinel/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Centinel" version="1.6.0.0" active="true">
+    <module name="Magento_Centinel" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Payment"/>
             <module name="Magento_Checkout"/>
diff --git a/app/code/Magento/Checkout/etc/module.xml b/app/code/Magento/Checkout/etc/module.xml
index 9ce20e05288..a4558a93dc1 100644
--- a/app/code/Magento/Checkout/etc/module.xml
+++ b/app/code/Magento/Checkout/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Checkout" version="1.6.0.0" active="true">
+    <module name="Magento_Checkout" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Sales"/>
             <module name="Magento_CatalogInventory"/>
diff --git a/app/code/Magento/CheckoutAgreements/etc/module.xml b/app/code/Magento/CheckoutAgreements/etc/module.xml
index 32e7c203f9a..9c3698c7793 100644
--- a/app/code/Magento/CheckoutAgreements/etc/module.xml
+++ b/app/code/Magento/CheckoutAgreements/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_CheckoutAgreements" version="1.0.0.0" active="true">
+    <module name="Magento_CheckoutAgreements" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core" />
             <module name="Magento_Store" />
diff --git a/app/code/Magento/Cms/etc/module.xml b/app/code/Magento/Cms/etc/module.xml
index f06763b7280..a1e90deba9c 100644
--- a/app/code/Magento/Cms/etc/module.xml
+++ b/app/code/Magento/Cms/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Cms" version="2.0.0.0" active="true">
+    <module name="Magento_Cms" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml
index a3b9a10ce9a..35789f99cbe 100644
--- a/app/code/Magento/ConfigurableProduct/etc/di.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/di.xml
@@ -61,13 +61,6 @@
             </argument>
         </arguments>
     </type>
-    <type name="Magento\ImportExport\Model\Export\RowCustomizer\Composite">
-        <arguments>
-            <argument name="customizers" xsi:type="array">
-                <item name="configurableProduct" xsi:type="string">Magento\ConfigurableProduct\Model\Export\RowCustomizer</item>
-            </argument>
-        </arguments>
-    </type>
     <type name="Magento\Eav\Model\Entity\Setup\PropertyMapper\Composite">
         <arguments>
             <argument name="propertyMappers" xsi:type="array">
diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml
index 3779cf96d86..7601658945a 100644
--- a/app/code/Magento/ConfigurableProduct/etc/module.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_ConfigurableProduct" version="1.0.0.0" active="true">
+    <module name="Magento_ConfigurableProduct" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_CatalogInventory"/>
@@ -43,7 +43,6 @@
             <module name="Magento_Backend" />
             <module name="Magento_Eav" />
             <module name="Magento_Cms" />
-            <module name="Magento_ImportExport" />
             <module name="Magento_Customer" />
             <module name="Magento_CatalogRule" />
             <module name="Magento_Directory" />
diff --git a/app/code/Magento/Connect/etc/module.xml b/app/code/Magento/Connect/etc/module.xml
index 24f1b50b98c..8930208afa6 100644
--- a/app/code/Magento/Connect/etc/module.xml
+++ b/app/code/Magento/Connect/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Connect" version="1.6.0.0" active="true">
+    <module name="Magento_Connect" schema_version="1.6.0.0" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Core"/>
diff --git a/app/code/Magento/Contact/etc/module.xml b/app/code/Magento/Contact/etc/module.xml
index d0181bcdf9d..48aad3b40e8 100644
--- a/app/code/Magento/Contact/etc/module.xml
+++ b/app/code/Magento/Contact/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Contact" version="1.6.0.0" active="true">
+    <module name="Magento_Contact" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Core/etc/di.xml b/app/code/Magento/Core/etc/di.xml
index 7746ba1f0d8..11f0d9edf03 100644
--- a/app/code/Magento/Core/etc/di.xml
+++ b/app/code/Magento/Core/etc/di.xml
@@ -271,11 +271,6 @@
             <argument name="cacheId" xsi:type="string">fieldset_config</argument>
         </arguments>
     </type>
-    <type name="Magento\Framework\Locale\Hierarchy\Config">
-        <arguments>
-            <argument name="reader" xsi:type="object">Magento\Framework\Locale\Hierarchy\Config\Reader</argument>
-        </arguments>
-    </type>
     <type name="Magento\Framework\DB\Helper">
         <arguments>
             <argument name="modulePrefix" xsi:type="string">core</argument>
diff --git a/app/code/Magento/Core/etc/module.xml b/app/code/Magento/Core/etc/module.xml
index a48515d1fb7..f0f46573fdd 100644
--- a/app/code/Magento/Core/etc/module.xml
+++ b/app/code/Magento/Core/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Core" version="1.6.0.16" active="true">
+    <module name="Magento_Core" schema_version="1.6.0.16" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Backend"/>
diff --git a/app/code/Magento/Cron/etc/module.xml b/app/code/Magento/Cron/etc/module.xml
index 98f73ba7c4e..c4fa40f4b81 100644
--- a/app/code/Magento/Cron/etc/module.xml
+++ b/app/code/Magento/Cron/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Cron" version="1.6.0.0" active="true">
+    <module name="Magento_Cron" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Store"/>
         </sequence>
diff --git a/app/code/Magento/CurrencySymbol/etc/module.xml b/app/code/Magento/CurrencySymbol/etc/module.xml
index 572b7c34aa4..c8cd1384a86 100644
--- a/app/code/Magento/CurrencySymbol/etc/module.xml
+++ b/app/code/Magento/CurrencySymbol/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_CurrencySymbol" version="1.0.0.0.0" active="true">
+    <module name="Magento_CurrencySymbol" schema_version="1.0.0.0.0" active="true">
         <sequence>
             <module name="Magento_Widget"/>
         </sequence>
diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index.php b/app/code/Magento/Customer/Controller/Adminhtml/Index.php
index 8d93dd946f3..7a07a12c9b6 100644
--- a/app/code/Magento/Customer/Controller/Adminhtml/Index.php
+++ b/app/code/Magento/Customer/Controller/Adminhtml/Index.php
@@ -619,39 +619,6 @@ class Index extends \Magento\Backend\App\Action
         return $result;
     }
 
-    /**
-     * Export customer grid to CSV format
-     *
-     * @return \Magento\Framework\App\ResponseInterface
-     */
-    public function exportCsvAction()
-    {
-        $this->_view->loadLayout();
-        $fileName = 'customers.csv';
-        /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock  */
-        $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export');
-        return $this->_fileFactory->create(
-            $fileName,
-            $exportBlock->getCsvFile(),
-            \Magento\Framework\App\Filesystem::VAR_DIR
-        );
-    }
-
-    /**
-     * Export customer grid to XML format
-     *
-     * @return \Magento\Framework\App\ResponseInterface
-     */
-    public function exportXmlAction()
-    {
-        $this->_view->loadLayout();
-        $fileName = 'customers.xml';
-        /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock  */
-        $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export');
-        $content = $exportBlock->getExcelFile($fileName);
-        return $this->_fileFactory->create($fileName, $content, \Magento\Framework\App\Filesystem::VAR_DIR);
-    }
-
     /**
      * Customer orders grid
      *
diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
index 4dae23458ad..c9e5159b97e 100644
--- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php
+++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
@@ -142,16 +142,17 @@ class AbstractAddress extends \Magento\Framework\Model\AbstractModel
     public function getName()
     {
         $name = '';
-        $config = $this->_eavConfig;
-        if ($config->getAttribute('customer_address', 'prefix')->getIsVisible() && $this->getPrefix()) {
+        if ($this->_eavConfig->getAttribute('customer_address', 'prefix')->getIsVisible() && $this->getPrefix()) {
             $name .= $this->getPrefix() . ' ';
         }
         $name .= $this->getFirstname();
-        if ($config->getAttribute('customer_address', 'middlename')->getIsVisible() && $this->getMiddlename()) {
+        if ($this->_eavConfig->getAttribute('customer_address', 'middlename')->getIsVisible()
+            && $this->getMiddlename()
+        ) {
             $name .= ' ' . $this->getMiddlename();
         }
         $name .= ' ' . $this->getLastname();
-        if ($config->getAttribute('customer_address', 'suffix')->getIsVisible() && $this->getSuffix()) {
+        if ($this->_eavConfig->getAttribute('customer_address', 'suffix')->getIsVisible() && $this->getSuffix()) {
             $name .= ' ' . $this->getSuffix();
         }
         return $name;
@@ -170,7 +171,7 @@ class AbstractAddress extends \Magento\Framework\Model\AbstractModel
         $lines = explode("\n", $this->getStreetFull());
         if (0 === $line || $line === null) {
             return $lines;
-        } else if (isset($lines[$line - 1])) {
+        } elseif (isset($lines[$line - 1])) {
             return $lines[$line - 1];
         } else {
             return '';
@@ -253,7 +254,7 @@ class AbstractAddress extends \Magento\Framework\Model\AbstractModel
     {
         if (is_array($key)) {
             $key = $this->_implodeStreetField($key);
-        } else if ($key == 'street') {
+        } elseif ($key == 'street') {
             $value = $this->_implodeStreetValue($value);
         }
         return parent::setData($key, $value);
@@ -313,24 +314,17 @@ class AbstractAddress extends \Magento\Framework\Model\AbstractModel
         $regionId = $this->getData('region_id');
         $region = $this->getData('region');
 
-        if ($regionId) {
-            if ($this->getRegionModel($regionId)->getCountryId() == $this->getCountryId()) {
-                $region = $this->getRegionModel($regionId)->getName();
-                $this->setData('region', $region);
-            }
-        }
-
-        if (!empty($region) && is_string($region)) {
-            $this->setData('region', $region);
-        } elseif (!$regionId && is_numeric($region)) {
+        if (!$regionId && is_numeric($region)) {
             if ($this->getRegionModel($region)->getCountryId() == $this->getCountryId()) {
                 $this->setData('region', $this->getRegionModel($region)->getName());
                 $this->setData('region_id', $region);
             }
-        } elseif ($regionId && !$region) {
+        } elseif ($regionId) {
             if ($this->getRegionModel($regionId)->getCountryId() == $this->getCountryId()) {
                 $this->setData('region', $this->getRegionModel($regionId)->getName());
             }
+        } elseif (is_string($region)) {
+            $this->setData('region', $region);
         }
 
         return $this->getData('region');
diff --git a/app/code/Magento/Customer/Model/Address/Converter.php b/app/code/Magento/Customer/Model/Address/Converter.php
index 84d61f66067..50f0ddb4d8c 100644
--- a/app/code/Magento/Customer/Model/Address/Converter.php
+++ b/app/code/Magento/Customer/Model/Address/Converter.php
@@ -30,7 +30,6 @@ use Magento\Customer\Service\V1\Data\AddressBuilder;
 use Magento\Customer\Model\Address as AddressModel;
 use Magento\Customer\Model\Address\AbstractAddress;
 use Magento\Customer\Service\V1\Data\Region;
-use Magento\Customer\Service\V1\Data\RegionBuilder;
 use Magento\Customer\Service\V1\CustomerMetadataServiceInterface;
 use Magento\Customer\Service\V1\Data\AddressConverter;
 
@@ -54,33 +53,25 @@ class Converter
      */
     protected $_addressFactory;
 
-    /**
-     * @var RegionBuilder
-     */
-    private $_regionBuilder;
-
     /**
      * Customer metadata service
      *
      * @var \Magento\Customer\Service\V1\CustomerMetadataServiceInterface
      */
-    private $_metadataService;
+    protected $_metadataService;
 
     /**
      * @param AddressBuilder $addressBuilder
      * @param AddressFactory $addressFactory
-     * @param RegionBuilder $regionBuilder
      * @param CustomerMetadataServiceInterface $metadataService
      */
     public function __construct(
         AddressBuilder $addressBuilder,
         AddressFactory $addressFactory,
-        RegionBuilder $regionBuilder,
         CustomerMetadataServiceInterface $metadataService
     ) {
         $this->_addressBuilder = $addressBuilder;
         $this->_addressFactory = $addressFactory;
-        $this->_regionBuilder = $regionBuilder;
         $this->_metadataService = $metadataService;
     }
 
@@ -110,7 +101,7 @@ class Converter
         // Set all attributes
         $attributes = AddressConverter::toFlatArray($address);
         foreach ($attributes as $attributeCode => $attributeData) {
-            if (Address::KEY_REGION == $attributeCode && $address->getRegion() instanceof Region) {
+            if (Address::KEY_REGION === $attributeCode && $address->getRegion() instanceof Region) {
                 $addressModel->setDataUsingMethod(Region::KEY_REGION, $address->getRegion()->getRegion());
                 $addressModel->setDataUsingMethod(Region::KEY_REGION_CODE, $address->getRegion()->getRegionCode());
                 $addressModel->setDataUsingMethod(Region::KEY_REGION_ID, $address->getRegion()->getRegionId());
@@ -170,9 +161,7 @@ class Converter
         }
 
         if ($addressModel->getCustomerId() || $addressModel->getParentId()) {
-            $customerId = $addressModel->getCustomerId() ? $addressModel
-                ->getCustomerId() : $addressModel
-                ->getParentId();
+            $customerId = $addressModel->getCustomerId() ?: $addressModel->getParentId();
             $this->_addressBuilder->setCustomerId($customerId);
         }
 
diff --git a/app/code/Magento/Customer/Model/Converter.php b/app/code/Magento/Customer/Model/Converter.php
index 911e43fd6a3..f714ccc5f4e 100644
--- a/app/code/Magento/Customer/Model/Converter.php
+++ b/app/code/Magento/Customer/Model/Converter.php
@@ -28,6 +28,7 @@ use Magento\Framework\Exception\NoSuchEntityException;
 use Magento\Customer\Service\V1\Data\Customer as CustomerDataObject;
 use Magento\Customer\Service\V1\Data\CustomerBuilder as CustomerDataObjectBuilder;
 use Magento\Framework\Service\EavDataObjectConverter;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
  * Customer Model converter.
@@ -46,14 +47,24 @@ class Converter
      */
     protected $_customerFactory;
 
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
     /**
      * @param CustomerDataObjectBuilder $customerBuilder
      * @param CustomerFactory $customerFactory
+     * @param StoreManagerInterface $storeManager
      */
-    public function __construct(CustomerDataObjectBuilder $customerBuilder, CustomerFactory $customerFactory)
-    {
+    public function __construct(
+        CustomerDataObjectBuilder $customerBuilder,
+        CustomerFactory $customerFactory,
+        StoreManagerInterface $storeManager
+    ) {
         $this->_customerBuilder = $customerBuilder;
         $this->_customerFactory = $customerFactory;
+        $this->storeManager = $storeManager;
     }
 
     /**
@@ -120,7 +131,7 @@ class Converter
     {
         $customer = $this->_customerFactory->create();
         if (!isset($websiteId)) {
-            $websiteId = $this->_storeManager->getWebsiteId();
+            $websiteId = $this->storeManager->getDefaultStoreView()->getWebsiteId();
         }
         $customer->setWebsiteId($websiteId);
 
diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php
index 948aab750af..06071b38d08 100644
--- a/app/code/Magento/Customer/Model/Customer.php
+++ b/app/code/Magento/Customer/Model/Customer.php
@@ -702,16 +702,8 @@ class Customer extends \Magento\Framework\Model\AbstractModel
      */
     public function sendNewAccountEmail($type = 'registered', $backUrl = '', $storeId = '0')
     {
-        /**
-         * 'registered'   welcome email, when confirmation is disabled
-         * 'confirmed'    welcome email, when confirmation is enabled
-         * 'confirmation' email with confirmation link
-         */
-        $types = array(
-            'registered' => self::XML_PATH_REGISTER_EMAIL_TEMPLATE,
-            'confirmed' => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE,
-            'confirmation' => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE
-        );
+        $types = $this->getTemplateTypes();
+
         if (!isset($types[$type])) {
             throw new \Magento\Framework\Model\Exception(__('Wrong transactional account email type'));
         }
@@ -1301,4 +1293,22 @@ class Customer extends \Magento\Framework\Model\AbstractModel
     {
         return $this->_attributeFactory->create();
     }
+
+    /**
+     * @return array
+     */
+    protected function getTemplateTypes()
+    {
+        /**
+         * 'registered'   welcome email, when confirmation is disabled
+         * 'confirmed'    welcome email, when confirmation is enabled
+         * 'confirmation' email with confirmation link
+         */
+        $types = array(
+            'registered'   => self::XML_PATH_REGISTER_EMAIL_TEMPLATE,
+            'confirmed'    => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE,
+            'confirmation' => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE,
+        );
+        return $types;
+    }
 }
diff --git a/app/code/Magento/Customer/Service/V1/Data/Address.php b/app/code/Magento/Customer/Service/V1/Data/Address.php
index b305edc8cb5..fdb214b9a0b 100644
--- a/app/code/Magento/Customer/Service/V1/Data/Address.php
+++ b/app/code/Magento/Customer/Service/V1/Data/Address.php
@@ -27,13 +27,15 @@ namespace Magento\Customer\Service\V1\Data;
 
 class Address extends \Magento\Framework\Service\Data\Eav\AbstractObject
 {
-    /**#@+
-     * Constants defined for keys of array, makes typos less likely
-     */
+    // FIXME: This constant relates to a quote address object, not this Data Object
     const ADDRESS_TYPE_BILLING = 'billing';
 
+    // FIXME: This constant relates to a quote address object, not this Data Object
     const ADDRESS_TYPE_SHIPPING = 'shipping';
 
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
     const KEY_COUNTRY_ID = 'country_id';
 
     const KEY_DEFAULT_BILLING = 'default_billing';
diff --git a/app/code/Magento/Customer/Service/V1/Data/SearchResults.php b/app/code/Magento/Customer/Service/V1/Data/SearchResults.php
index 38a03fcb0ab..b4c6f1005b0 100644
--- a/app/code/Magento/Customer/Service/V1/Data/SearchResults.php
+++ b/app/code/Magento/Customer/Service/V1/Data/SearchResults.php
@@ -27,7 +27,7 @@ namespace Magento\Customer\Service\V1\Data;
 /**
  * SearchResults Service Data Object used for the search service requests
  */
-class SearchResults extends \Magento\Framework\Service\Data\AbstractObject
+class SearchResults extends \Magento\Framework\Service\V1\Data\SearchResults
 {
     /**
      * Get items
@@ -36,26 +36,6 @@ class SearchResults extends \Magento\Framework\Service\Data\AbstractObject
      */
     public function getItems()
     {
-        return is_null($this->_get('items')) ? array() : $this->_get('items');
-    }
-
-    /**
-     * Get search criteria
-     *
-     * @return \Magento\Framework\Service\V1\Data\SearchCriteria
-     */
-    public function getSearchCriteria()
-    {
-        return $this->_get('search_criteria');
-    }
-
-    /**
-     * Get total count
-     *
-     * @return int
-     */
-    public function getTotalCount()
-    {
-        return $this->_get('total_count');
+        return parent::getItems();
     }
 }
diff --git a/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php b/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php
index ec44597bc8b..1557a0cf0be 100644
--- a/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php
+++ b/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php
@@ -24,45 +24,40 @@
 
 namespace Magento\Customer\Service\V1\Data;
 
-use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Framework\Service\Data\ObjectFactory;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+use Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder;
 
 /**
  * Builder for the SearchResults Service Data Object
  *
- * @method SearchResults create()
+ * @method \Magento\Customer\Service\V1\Data\SearchResults create()
  */
-class SearchResultsBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+class SearchResultsBuilder extends AbstractSearchResultsBuilder
 {
     /**
-     * Set search criteria
+     * Constructor
      *
-     * @param SearchCriteria $searchCriteria
-     * @return $this
+     * @param ObjectFactory $objectFactory
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param CustomerDetailsBuilder $customerDetailsObjectBuilder
      */
-    public function setSearchCriteria(SearchCriteria $searchCriteria)
-    {
-        return $this->_set('search_criteria', $searchCriteria);
-    }
-
-    /**
-     * Set total count
-     *
-     * @param int $totalCount
-     * @return $this
-     */
-    public function setTotalCount($totalCount)
-    {
-        return $this->_set('total_count', $totalCount);
+    public function __construct(
+        ObjectFactory $objectFactory,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        CustomerDetailsBuilder $customerDetailsObjectBuilder
+    ) {
+        parent::__construct($objectFactory, $searchCriteriaBuilder, $customerDetailsObjectBuilder);
     }
 
     /**
-     * Set items
+     * Set customer details items
      *
-     * @param \Magento\Customer\Service\V1\Data\CustomerDetails[] $items
+     * @param \Magento\Customer\Service\V1\Data\CustomerDetails[] $customerDetailsItems
      * @return $this
      */
-    public function setItems($items)
+    public function setItems($customerDetailsItems)
     {
-        return $this->_set('items', $items);
+        return parent::setItems($customerDetailsItems);
     }
 }
diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml
index 5e929dc6495..dcbc481bf7d 100644
--- a/app/code/Magento/Customer/etc/config.xml
+++ b/app/code/Magento/Customer/etc/config.xml
@@ -103,11 +103,5 @@ T: {{var telephone}}
 {{depend vat_id}}<br/>VAT: {{var vat_id}}{{/depend}}|]]></pdf>
             </address_templates>
         </customer>
-        <export>
-            <customer_page_size>
-                <customer>10000</customer>
-                <address>5000</address>
-            </customer_page_size>
-        </export>
     </default>
 </config>
diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml
index c69e0ccb726..91d05a2966c 100644
--- a/app/code/Magento/Customer/etc/module.xml
+++ b/app/code/Magento/Customer/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Customer" version="1.6.2.0.5" active="true">
+    <module name="Magento_Customer" schema_version="1.6.2.0.5" active="true">
         <sequence>
             <module name="Magento_Eav"/>
             <module name="Magento_Directory"/>
@@ -46,7 +46,6 @@
             <module name="Magento_Review"/>
             <module name="Magento_Tax"/>
             <module name="Magento_PageCache"/>
-            <module name="Magento_ImportExport"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/Customer/etc/webapi.xml b/app/code/Magento/Customer/etc/webapi.xml
index 44c3142d66e..2d2179ffa7a 100644
--- a/app/code/Magento/Customer/etc/webapi.xml
+++ b/app/code/Magento/Customer/etc/webapi.xml
@@ -140,7 +140,7 @@
     <route url="/V1/customerAccounts" method="POST">
         <service class="Magento\Customer\Service\V1\CustomerAccountServiceInterface" method="createCustomer"/>
         <resources>
-            <resource ref="Magento_Customer::customer"/>
+            <resource ref="anonymous"/>
         </resources>
     </route>
     <route url="/V1/customerAccounts" method="PUT">
@@ -155,6 +155,15 @@
             <resource ref="Magento_Customer::customer"/>
         </resources>
     </route>
+    <route url="/V1/customer/me" method="GET">
+        <service class="Magento\Customer\Service\V1\CustomerAccountServiceInterface" method="getCustomer"/>
+        <resources>
+            <resource ref="self"/>
+        </resources>
+        <data>
+            <parameter name="customerId" force="true" source="session" method="getUserId">null</parameter>
+        </data>
+    </route>
     <route url="/V1/customerAccounts/:customerId/customer" method="GET">
         <service class="Magento\Customer\Service\V1\CustomerAccountServiceInterface" method="getCustomer"/>
         <resources>
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml
index f9ff7bdfb00..765642a13ca 100644
--- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml
+++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml
@@ -38,20 +38,6 @@
                     <param name="_current">1</param>
                 </argument>
             </arguments>
-            <block class="Magento\Backend\Block\Widget\Grid\Export" name="admin.block.customer.grid.export" as="grid.export">
-                <arguments>
-                    <argument name="exportTypes" xsi:type="array">
-                        <item name="csv" xsi:type="array">
-                            <item name="urlPath" xsi:type="string">customer/*/exportCsv</item>
-                            <item name="label" xsi:type="string" translate="true">CSV</item>
-                        </item>
-                        <item name="excel" xsi:type="array">
-                            <item name="urlPath" xsi:type="string">customer/*/exportXml</item>
-                            <item name="label" xsi:type="string" translate="true">Excel XML</item>
-                        </item>
-                    </argument>
-                </arguments>
-            </block>
             <block class="Magento\Backend\Block\Widget\Grid\Massaction" name="admin.block.customer.grid.massaction" as="grid.massaction">
                 <arguments>
                     <argument name="massaction_id_field" xsi:type="string">entity_id</argument>
diff --git a/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php
new file mode 100644
index 00000000000..c5a7c5ba225
--- /dev/null
+++ b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CustomerImportExport\Controller\Adminhtml;
+
+/**
+ * Class Index
+ */
+class Index extends \Magento\Backend\App\Action
+{
+    /**
+     * @var \Magento\Framework\App\Response\Http\FileFactory
+     */
+    protected $_fileFactory;
+
+    /**
+     * @param \Magento\Backend\App\Action\Context $context
+     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+     */
+    public function __construct(
+        \Magento\Backend\App\Action\Context $context,
+        \Magento\Framework\App\Response\Http\FileFactory $fileFactory
+    ) {
+        $this->_fileFactory = $fileFactory;
+        parent::__construct($context);
+    }
+
+    /**
+     * Export customer grid to CSV format
+     *
+     * @return \Magento\Framework\App\ResponseInterface
+     */
+    public function exportCsvAction()
+    {
+        $this->_view->loadLayout();
+        $fileName = 'customers.csv';
+        /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock  */
+        $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export');
+        return $this->_fileFactory->create(
+            $fileName,
+            $exportBlock->getCsvFile(),
+            \Magento\Framework\App\Filesystem::VAR_DIR
+        );
+    }
+
+    /**
+     * Export customer grid to XML format
+     *
+     * @return \Magento\Framework\App\ResponseInterface
+     */
+    public function exportXmlAction()
+    {
+        $this->_view->loadLayout();
+        $fileName = 'customers.xml';
+        /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock  */
+        $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export');
+        $content = $exportBlock->getExcelFile($fileName);
+        return $this->_fileFactory->create($fileName, $content, \Magento\Framework\App\Filesystem::VAR_DIR);
+    }
+}
diff --git a/app/code/Magento/Customer/Model/ImportExport/Export/Address.php b/app/code/Magento/CustomerImportExport/Model/Export/Address.php
similarity index 97%
rename from app/code/Magento/Customer/Model/ImportExport/Export/Address.php
rename to app/code/Magento/CustomerImportExport/Model/Export/Address.php
index e4dfce921f2..bd8929afe95 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Export/Address.php
+++ b/app/code/Magento/CustomerImportExport/Model/Export/Address.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
 class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav
 {
@@ -124,7 +124,7 @@ class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerColFactory
-     * @param \Magento\Customer\Model\ImportExport\Export\CustomerFactory $eavCustomerFactory
+     * @param \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory
      * @param \Magento\Customer\Model\Resource\Address\CollectionFactory $addressColFactory
      * @param array $data
      */
@@ -136,7 +136,7 @@ class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerColFactory,
-        \Magento\Customer\Model\ImportExport\Export\CustomerFactory $eavCustomerFactory,
+        \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory,
         \Magento\Customer\Model\Resource\Address\CollectionFactory $addressColFactory,
         array $data = array()
     ) {
diff --git a/app/code/Magento/Customer/Model/ImportExport/Export/Customer.php b/app/code/Magento/CustomerImportExport/Model/Export/Customer.php
similarity index 99%
rename from app/code/Magento/Customer/Model/ImportExport/Export/Customer.php
rename to app/code/Magento/CustomerImportExport/Model/Export/Customer.php
index a92369d3d71..58bda0850c8 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Export/Customer.php
+++ b/app/code/Magento/CustomerImportExport/Model/Export/Customer.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
 /**
  * Export entity customer model
diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php
similarity index 95%
rename from app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php
rename to app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php
index 846d3863f82..2af423a8098 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
-use Magento\Customer\Model\Resource\ImportExport\Import\Customer\Storage;
+use Magento\CustomerImportExport\Model\Resource\Import\Customer\Storage;
 
 /**
  * Import entity abstract customer model
@@ -76,7 +76,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit
     protected $_customerStorage;
 
     /**
-     * @var \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory
+     * @var \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory
      */
     protected $_storageFactory;
 
@@ -95,7 +95,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory
      * @param \Magento\Eav\Model\Config $eavConfig
-     * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory
+     * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory
      * @param array $data
      */
     public function __construct(
@@ -108,7 +108,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\ImportExport\Model\Export\Factory $collectionFactory,
         \Magento\Eav\Model\Config $eavConfig,
-        \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory,
+        \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory,
         array $data = array()
     ) {
         $this->_storageFactory = $storageFactory;
diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php
similarity index 98%
rename from app/code/Magento/Customer/Model/ImportExport/Import/Address.php
rename to app/code/Magento/CustomerImportExport/Model/Import/Address.php
index 168925e2980..e685f184a64 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Import/Address.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class Address extends AbstractCustomer
 {
@@ -236,7 +236,7 @@ class Address extends AbstractCustomer
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory
      * @param \Magento\Eav\Model\Config $eavConfig
-     * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory
+     * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory
      * @param \Magento\Customer\Model\AddressFactory $addressFactory
      * @param \Magento\Directory\Model\Resource\Region\CollectionFactory $regionColFactory
      * @param \Magento\Customer\Model\CustomerFactory $customerFactory
@@ -255,7 +255,7 @@ class Address extends AbstractCustomer
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\ImportExport\Model\Export\Factory $collectionFactory,
         \Magento\Eav\Model\Config $eavConfig,
-        \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory,
+        \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory,
         \Magento\Customer\Model\AddressFactory $addressFactory,
         \Magento\Directory\Model\Resource\Region\CollectionFactory $regionColFactory,
         \Magento\Customer\Model\CustomerFactory $customerFactory,
diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
similarity index 98%
rename from app/code/Magento/Customer/Model/ImportExport/Import/Customer.php
rename to app/code/Magento/CustomerImportExport/Model/Import/Customer.php
index bf67390988b..86a21879948 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Import/Customer.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class Customer extends AbstractCustomer
 {
@@ -142,7 +142,7 @@ class Customer extends AbstractCustomer
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory
      * @param \Magento\Eav\Model\Config $eavConfig
-     * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory
+     * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory
      * @param \Magento\Customer\Model\Resource\Attribute\CollectionFactory $attrCollectionFactory
      * @param \Magento\Customer\Model\CustomerFactory $customerFactory
      * @param array $data
@@ -157,7 +157,7 @@ class Customer extends AbstractCustomer
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\ImportExport\Model\Export\Factory $collectionFactory,
         \Magento\Eav\Model\Config $eavConfig,
-        \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory,
+        \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory,
         \Magento\Customer\Model\Resource\Attribute\CollectionFactory $attrCollectionFactory,
         \Magento\Customer\Model\CustomerFactory $customerFactory,
         array $data = array()
diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
similarity index 95%
rename from app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php
rename to app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
index 73129b34dc8..0a668311f52 100644
--- a/app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 /**
  * Import entity customer combined model
@@ -68,12 +68,12 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit
     const ERROR_ROW_IS_ORPHAN = 'rowIsOrphan';
 
     /**
-     * @var \Magento\Customer\Model\ImportExport\Import\Customer
+     * @var \Magento\CustomerImportExport\Model\Import\Customer
      */
     protected $_customerEntity;
 
     /**
-     * @var \Magento\Customer\Model\ImportExport\Import\Address
+     * @var \Magento\CustomerImportExport\Model\Import\Address
      */
     protected $_addressEntity;
 
@@ -153,9 +153,9 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit
      * @param \Magento\ImportExport\Model\ImportFactory $importFactory
      * @param \Magento\ImportExport\Model\Resource\Helper $resourceHelper
      * @param \Magento\Framework\App\Resource $resource
-     * @param \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory $dataFactory
-     * @param \Magento\Customer\Model\ImportExport\Import\CustomerFactory $customerFactory
-     * @param \Magento\Customer\Model\ImportExport\Import\AddressFactory $addressFactory
+     * @param \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory $dataFactory
+     * @param \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory
+     * @param \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory
      * @param array $data
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -167,9 +167,9 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit
         \Magento\ImportExport\Model\ImportFactory $importFactory,
         \Magento\ImportExport\Model\Resource\Helper $resourceHelper,
         \Magento\Framework\App\Resource $resource,
-        \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory $dataFactory,
-        \Magento\Customer\Model\ImportExport\Import\CustomerFactory $customerFactory,
-        \Magento\Customer\Model\ImportExport\Import\AddressFactory $addressFactory,
+        \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory $dataFactory,
+        \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory,
+        \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory,
         array $data = array()
     ) {
         parent::__construct($coreData, $string, $scopeConfig, $importFactory, $resourceHelper, $resource, $data);
diff --git a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php b/app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php
similarity index 98%
rename from app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php
rename to app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php
index be27ccdc9a6..1808b39b81e 100644
--- a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php
+++ b/app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\Resource\ImportExport\Import\Customer;
+namespace Magento\CustomerImportExport\Model\Resource\Import\Customer;
 
 class Storage
 {
diff --git a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php b/app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php
similarity index 96%
rename from app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php
rename to app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php
index e3afc316e83..87855c948da 100644
--- a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php
+++ b/app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite;
+namespace Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite;
 
-use Magento\Customer\Model\ImportExport\Import\CustomerComposite;
+use Magento\CustomerImportExport\Model\Import\CustomerComposite;
 
 class Data extends \Magento\ImportExport\Model\Resource\Import\Data
 {
diff --git a/app/code/Magento/ConfigurableProduct/etc/export.xml b/app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml
similarity index 77%
rename from app/code/Magento/ConfigurableProduct/etc/export.xml
rename to app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml
index 5c91ae4c28b..45c5ae96914 100644
--- a/app/code/Magento/ConfigurableProduct/etc/export.xml
+++ b/app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml
@@ -23,6 +23,10 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/export.xsd">
-    <productType name="configurable" model="Magento\ConfigurableProduct\Model\Export\Entity\Product\Type\Configurable" />
-</config>
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
+    <router id="admin">
+        <route id="customer_import_export" frontName="customer_import_export">
+            <module name="Magento_CustomerImportExport" />
+        </route>
+    </router>
+</config>
\ No newline at end of file
diff --git a/app/code/Magento/ConfigurableProduct/etc/import.xml b/app/code/Magento/CustomerImportExport/etc/config.xml
similarity index 79%
rename from app/code/Magento/ConfigurableProduct/etc/import.xml
rename to app/code/Magento/CustomerImportExport/etc/config.xml
index b1225ec43dd..134643cda80 100644
--- a/app/code/Magento/ConfigurableProduct/etc/import.xml
+++ b/app/code/Magento/CustomerImportExport/etc/config.xml
@@ -23,6 +23,13 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/import.xsd">
-    <productType name="configurable" model="Magento\ConfigurableProduct\Model\Import\Entity\Product\Type\Configurable" />
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd">
+    <default>
+        <export>
+            <customer_page_size>
+                <customer>10000</customer>
+                <address>5000</address>
+            </customer_page_size>
+        </export>
+    </default>
 </config>
diff --git a/app/code/Magento/Customer/etc/export.xml b/app/code/Magento/CustomerImportExport/etc/export.xml
similarity index 86%
rename from app/code/Magento/Customer/etc/export.xml
rename to app/code/Magento/CustomerImportExport/etc/export.xml
index d04a6666962..cd125c8ab80 100644
--- a/app/code/Magento/Customer/etc/export.xml
+++ b/app/code/Magento/CustomerImportExport/etc/export.xml
@@ -24,6 +24,6 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/export.xsd">
-    <entity name="customer" label="Customers Main File" model="Magento\Customer\Model\ImportExport\Export\Customer" />
-    <entity name="customer_address" label="Customer Addresses" model="Magento\Customer\Model\ImportExport\Export\Address" />
+    <entity name="customer" label="Customers Main File" model="Magento\CustomerImportExport\Model\Export\Customer" entityAttributeFilterType="customer"/>
+    <entity name="customer_address" label="Customer Addresses" model="Magento\CustomerImportExport\Model\Export\Address" entityAttributeFilterType="customer" />
 </config>
diff --git a/app/code/Magento/Customer/etc/import.xml b/app/code/Magento/CustomerImportExport/etc/import.xml
similarity index 76%
rename from app/code/Magento/Customer/etc/import.xml
rename to app/code/Magento/CustomerImportExport/etc/import.xml
index 5513b3ea241..9ac4c55985d 100644
--- a/app/code/Magento/Customer/etc/import.xml
+++ b/app/code/Magento/CustomerImportExport/etc/import.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/import.xsd">
-    <entity name="customer_composite" label="Customers" model="Magento\Customer\Model\ImportExport\Import\CustomerComposite" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
-    <entity name="customer" label="Customers Main File" model="Magento\Customer\Model\ImportExport\Import\Customer" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Custom" />
-    <entity name="customer_address" label="Customer Addresses" model="Magento\Customer\Model\ImportExport\Import\Address" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Custom" />
+    <entity name="customer_composite" label="Customers" model="Magento\CustomerImportExport\Model\Import\CustomerComposite" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
+    <entity name="customer" label="Customers Main File" model="Magento\CustomerImportExport\Model\Import\Customer" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Custom" />
+    <entity name="customer_address" label="Customer Addresses" model="Magento\CustomerImportExport\Model\Import\Address" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Custom" />
 </config>
diff --git a/app/code/Magento/CustomerImportExport/etc/module.xml b/app/code/Magento/CustomerImportExport/etc/module.xml
new file mode 100644
index 00000000000..c86315663dc
--- /dev/null
+++ b/app/code/Magento/CustomerImportExport/etc/module.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Magento_CustomerImportExport" schema_version="1.0.0.0" active="true">
+        <depends>
+            <module name="Magento_Backend"/>
+            <module name="Magento_Core"/>
+            <module name="Magento_Customer"/>
+            <module name="Magento_Eav"/>
+            <module name="Magento_ImportExport"/>
+            <module name="Magento_Store"/>
+            <module name="Magento_Directory"/>
+        </depends>
+    </module>
+</config>
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportcsv.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportcsv.xml
similarity index 100%
rename from app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportcsv.xml
rename to app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportcsv.xml
diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportxml.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml
similarity index 100%
rename from app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportxml.xml
rename to app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml
diff --git a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml
new file mode 100644
index 00000000000..019d8f08b4a
--- /dev/null
+++ b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceBlock name="admin.block.customer.grid">
+        <block class="Magento\Backend\Block\Widget\Grid\Export" name="admin.block.customer.grid.export" as="grid.export">
+            <arguments>
+                <argument name="exportTypes" xsi:type="array">
+                    <item name="csv" xsi:type="array">
+                        <item name="urlPath" xsi:type="string">customer_import_export/*/exportCsv</item>
+                        <item name="label" xsi:type="string" translate="true">CSV</item>
+                    </item>
+                    <item name="excel" xsi:type="array">
+                        <item name="urlPath" xsi:type="string">customer_import_export/*/exportXml</item>
+                        <item name="label" xsi:type="string" translate="true">Excel XML</item>
+                    </item>
+                </argument>
+            </arguments>
+        </block>
+    </referenceBlock>
+</layout>
diff --git a/app/code/Magento/DesignEditor/etc/module.xml b/app/code/Magento/DesignEditor/etc/module.xml
index 9cdbed9c9d0..19dc07ee289 100644
--- a/app/code/Magento/DesignEditor/etc/module.xml
+++ b/app/code/Magento/DesignEditor/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_DesignEditor" version="1.0.0.3" active="true">
+    <module name="Magento_DesignEditor" schema_version="1.0.0.3" active="true">
         <sequence>
             <module name="Magento_Theme"/>
         </sequence>
diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml
index 63ad7d98695..f2422aba3b8 100644
--- a/app/code/Magento/Dhl/etc/module.xml
+++ b/app/code/Magento/Dhl/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Dhl" version="2.0.0.0" active="true">
+    <module name="Magento_Dhl" schema_version="2.0.0.0" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Shipping"/>
diff --git a/app/code/Magento/Directory/etc/module.xml b/app/code/Magento/Directory/etc/module.xml
index 4ebeb70547d..3a7eb13d653 100644
--- a/app/code/Magento/Directory/etc/module.xml
+++ b/app/code/Magento/Directory/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Directory" version="1.6.0.2" active="true">
+    <module name="Magento_Directory" schema_version="1.6.0.2" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Downloadable/etc/module.xml b/app/code/Magento/Downloadable/etc/module.xml
index be2513d638d..d17b2b48cbd 100644
--- a/app/code/Magento/Downloadable/etc/module.xml
+++ b/app/code/Magento/Downloadable/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Downloadable" version="1.6.0.0.3" active="true">
+    <module name="Magento_Downloadable" schema_version="1.6.0.0.3" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index 12b109b527c..d8351142626 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -536,9 +536,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractModel
     public function isValueEmpty($value)
     {
         $attrType = $this->getBackend()->getType();
-        $isEmpty = is_array(
-            $value
-        ) ||
+        $isEmpty = (is_array($value) && count($value) == 0) ||
             $value === null ||
             $value === false && $attrType != 'int' ||
             $value === '' && ($attrType == 'int' ||
diff --git a/app/code/Magento/Eav/etc/module.xml b/app/code/Magento/Eav/etc/module.xml
index d20dbc8669d..a07332047bb 100644
--- a/app/code/Magento/Eav/etc/module.xml
+++ b/app/code/Magento/Eav/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Eav" version="1.6.0.2" active="true">
+    <module name="Magento_Eav" schema_version="1.6.0.2" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Email/etc/module.xml b/app/code/Magento/Email/etc/module.xml
index a6e22904467..bbc8e18e27a 100644
--- a/app/code/Magento/Email/etc/module.xml
+++ b/app/code/Magento/Email/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Email" version="1.0.0.0" active="true">
+    <module name="Magento_Email" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Fedex/etc/module.xml b/app/code/Magento/Fedex/etc/module.xml
index f335996dc19..1635c68fe69 100644
--- a/app/code/Magento/Fedex/etc/module.xml
+++ b/app/code/Magento/Fedex/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Fedex" version="2.0.0.0" active="true">
+    <module name="Magento_Fedex" schema_version="2.0.0.0" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Shipping"/>
diff --git a/app/code/Magento/GiftMessage/etc/module.xml b/app/code/Magento/GiftMessage/etc/module.xml
index 9dd4428274f..4cf7227736e 100644
--- a/app/code/Magento/GiftMessage/etc/module.xml
+++ b/app/code/Magento/GiftMessage/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GiftMessage" version="1.6.0.1" active="true">
+    <module name="Magento_GiftMessage" schema_version="1.6.0.1" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Sales"/>
diff --git a/app/code/Magento/GoogleAdwords/etc/module.xml b/app/code/Magento/GoogleAdwords/etc/module.xml
index ca5ea54fe48..dbfe014290e 100644
--- a/app/code/Magento/GoogleAdwords/etc/module.xml
+++ b/app/code/Magento/GoogleAdwords/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GoogleAdwords" version="2.0.0.0" active="true">
+    <module name="Magento_GoogleAdwords" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Checkout"/>
         </sequence>
diff --git a/app/code/Magento/GoogleAnalytics/etc/module.xml b/app/code/Magento/GoogleAnalytics/etc/module.xml
index 3f2b5f92209..ca8c5f720e1 100644
--- a/app/code/Magento/GoogleAnalytics/etc/module.xml
+++ b/app/code/Magento/GoogleAnalytics/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GoogleAnalytics" version="1.6.0.0" active="true">
+    <module name="Magento_GoogleAnalytics" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/GoogleOptimizer/etc/module.xml b/app/code/Magento/GoogleOptimizer/etc/module.xml
index 8db326345d6..e54380514d7 100644
--- a/app/code/Magento/GoogleOptimizer/etc/module.xml
+++ b/app/code/Magento/GoogleOptimizer/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GoogleOptimizer" version="2.0.0.0" active="true">
+    <module name="Magento_GoogleOptimizer" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_GoogleAnalytics"/>
             <module name="Magento_Catalog"/>
diff --git a/app/code/Magento/GoogleShopping/etc/module.xml b/app/code/Magento/GoogleShopping/etc/module.xml
index 75d213e2b0b..f9ef0d68485 100644
--- a/app/code/Magento/GoogleShopping/etc/module.xml
+++ b/app/code/Magento/GoogleShopping/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GoogleShopping" version="1.6.0.0.1" active="true">
+    <module name="Magento_GoogleShopping" schema_version="1.6.0.0.1" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/GroupedProduct/etc/module.xml b/app/code/Magento/GroupedProduct/etc/module.xml
index f4d35a7d072..3363c1f1cb2 100644
--- a/app/code/Magento/GroupedProduct/etc/module.xml
+++ b/app/code/Magento/GroupedProduct/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_GroupedProduct" version="0.0.1" active="true">
+    <module name="Magento_GroupedProduct" schema_version="0.0.1" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_CatalogInventory"/>
@@ -42,7 +42,6 @@
             <module name="Magento_Eav" />
             <module name="Magento_Customer" />
             <module name="Magento_Theme" />
-            <module name="Magento_ImportExport" />
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/ImportExport/Helper/Data.php b/app/code/Magento/ImportExport/Helper/Data.php
index b1bb25070f6..e5c8acd37f5 100644
--- a/app/code/Magento/ImportExport/Helper/Data.php
+++ b/app/code/Magento/ImportExport/Helper/Data.php
@@ -101,7 +101,7 @@ class Data extends \Magento\Core\Helper\Data
     }
 
     /**
-     * Retrieve size of bunch (how much products should be involved in one import iteration)
+     * Retrieve size of bunch (how many entities should be involved in one import iteration)
      *
      * @return int
      */
diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php
index e33eb2612a0..1f455550661 100644
--- a/app/code/Magento/ImportExport/Model/Export/Config.php
+++ b/app/code/Magento/ImportExport/Model/Export/Config.php
@@ -49,13 +49,15 @@ class Config extends \Magento\Framework\Config\Data implements \Magento\ImportEx
     }
 
     /**
-     * Retrieve export product types configuration
+     * Retrieve export entity types configuration
      *
+     * @param string $entity
      * @return array
      */
-    public function getProductTypes()
+    public function getEntityTypes($entity)
     {
-        return $this->get('productTypes');
+        $entities = $this->getEntities();
+        return isset($entities[$entity]) ? $entities[$entity]['types'] : [];
     }
 
     /**
diff --git a/app/code/Magento/ImportExport/Model/Export/Config/Converter.php b/app/code/Magento/ImportExport/Model/Export/Config/Converter.php
index 7efef561c11..becbc4ec2fc 100644
--- a/app/code/Magento/ImportExport/Model/Export/Config/Converter.php
+++ b/app/code/Magento/ImportExport/Model/Export/Config/Converter.php
@@ -34,33 +34,43 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
      */
     public function convert($source)
     {
-        $output = array('entities' => array(), 'productTypes' => array(), 'fileFormats' => array());
+        $output = array('entities' => array(), 'fileFormats' => array());
         /** @var \DOMNodeList $entities */
         $entities = $source->getElementsByTagName('entity');
-        /** @var DOMNode $entityConfig */
+        /** @var \DOMNode $entityConfig */
         foreach ($entities as $entityConfig) {
             $attributes = $entityConfig->attributes;
             $name = $attributes->getNamedItem('name')->nodeValue;
             $label = $attributes->getNamedItem('label')->nodeValue;
             $model = $attributes->getNamedItem('model')->nodeValue;
+            $entityAttributeFilterType = $attributes->getNamedItem('entityAttributeFilterType')->nodeValue;
 
-            $output['entities'][$name] = array('name' => $name, 'label' => $label, 'model' => $model);
+            $output['entities'][$name] = array(
+                'name' => $name,
+                'label' => $label,
+                'model' => $model,
+                'types' => [],
+                'entityAttributeFilterType' => $entityAttributeFilterType
+            );
         }
 
-        /** @var \DOMNodeList $productTypes */
-        $productTypes = $source->getElementsByTagName('productType');
-        /** @var DOMNode $productTypeConfig */
-        foreach ($productTypes as $productTypeConfig) {
-            $attributes = $productTypeConfig->attributes;
+        /** @var \DOMNodeList $entityTypes */
+        $entityTypes = $source->getElementsByTagName('entityType');
+        /** @var \DOMNode $entityTypeConfig */
+        foreach ($entityTypes as $entityTypeConfig) {
+            $attributes = $entityTypeConfig->attributes;
             $model = $attributes->getNamedItem('model')->nodeValue;
             $name = $attributes->getNamedItem('name')->nodeValue;
+            $entity = $attributes->getNamedItem('entity')->nodeValue;
 
-            $output['productTypes'][$name] = array('name' => $name, 'model' => $model);
+            if (isset($output['entities'][$entity])) {
+                $output['entities'][$entity]['types'][$name] = array('name' => $name, 'model' => $model);
+            }
         }
 
         /** @var \DOMNodeList $fileFormats */
         $fileFormats = $source->getElementsByTagName('fileFormat');
-        /** @var DOMNode $fileFormatConfig */
+        /** @var \DOMNode $fileFormatConfig */
         foreach ($fileFormats as $fileFormatConfig) {
             $attributes = $fileFormatConfig->attributes;
             $name = $attributes->getNamedItem('name')->nodeValue;
diff --git a/app/code/Magento/ImportExport/Model/Export/Config/Reader.php b/app/code/Magento/ImportExport/Model/Export/Config/Reader.php
index 3af7804593e..e99cf220038 100644
--- a/app/code/Magento/ImportExport/Model/Export/Config/Reader.php
+++ b/app/code/Magento/ImportExport/Model/Export/Config/Reader.php
@@ -32,7 +32,7 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
      */
     protected $_idAttributes = array(
         '/config/entity' => 'name',
-        '/config/productType' => 'name',
+        '/config/entityType' => ['entity', 'name'],
         '/config/fileFormat' => 'name'
     );
 
diff --git a/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php b/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php
index f44dc05dc97..75c11464707 100644
--- a/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php
+++ b/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php
@@ -40,9 +40,10 @@ interface ConfigInterface
     public function getFileFormats();
 
     /**
-     * Retrieve import product types configuration
+     * Retrieve import entity types configuration
      *
+     * @param string $entity
      * @return array
      */
-    public function getProductTypes();
+    public function getEntityTypes($entity);
 }
diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php
index 9e2c52e6760..3d32f02d68d 100644
--- a/app/code/Magento/ImportExport/Model/Import.php
+++ b/app/code/Magento/ImportExport/Model/Import.php
@@ -75,15 +75,6 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
      */
     protected $_entityAdapter;
 
-    /**
-     * Entity invalidated indexes.
-     *
-     * @var \Magento\ImportExport\Model\Import\Entity\AbstractEntity
-     */
-    protected static $_entityInvalidatedIndexes = array(
-        'catalog_product' => array('catalog_product_price', 'catalogsearch_fulltext', 'catalog_product_flat')
-    );
-
     /**
      * Import export data
      *
@@ -470,66 +461,6 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
         return $this->_getEntityAdapter()->isImportAllowed();
     }
 
-    /**
-     * Import source file structure to DB.
-     *
-     * @return void
-     */
-    public function expandSource()
-    {
-        /** @var $writer \Magento\ImportExport\Model\Export\Adapter\Csv */
-        $writer = $this->_csvFactory->create(array('destination' => $this->getWorkingDir() . "big0.csv"));
-        $regExps = array('last' => '/(.*?)(\d+)$/', 'middle' => '/(.*?)(\d+)(.*)$/');
-        $colReg = array(
-            'sku' => 'last',
-            'name' => 'last',
-            'description' => 'last',
-            'short_description' => 'last',
-            'url_key' => 'middle',
-            'meta_title' => 'last',
-            'meta_keyword' => 'last',
-            'meta_description' => 'last',
-            '_related_sku' => 'last',
-            '_crosssell_sku' => 'last',
-            '_upsell_sku' => 'last',
-            '_custom_option_sku' => 'middle',
-            '_custom_option_row_sku' => 'middle',
-            '_super_products_sku' => 'last',
-            '_associated_sku' => 'last'
-        );
-        $size = self::DEFAULT_SIZE;
-
-        $filename = 'catalog_product.csv';
-        $filenameFormat = 'big%s.csv';
-        foreach ($this->_getSourceAdapter($this->getWorkingDir() . $filename) as $row) {
-            $writer->writeRow($row);
-        }
-        $count = self::MAX_IMPORT_CHUNKS;
-        for ($i = 1; $i < $count; $i++) {
-            $writer = $this->_csvFactory->create(
-                array('destination' => $this->getWorkingDir() . sprintf($filenameFormat, $i))
-            );
-
-            $adapter = $this->_getSourceAdapter($this->getWorkingDir() . sprintf($filenameFormat, $i - 1));
-            foreach ($adapter as $row) {
-                $writer->writeRow($row);
-            }
-            $adapter = $this->_getSourceAdapter($this->getWorkingDir() . sprintf($filenameFormat, $i - 1));
-            foreach ($adapter as $row) {
-                foreach ($colReg as $colName => $regExpType) {
-                    if (!empty($row[$colName])) {
-                        preg_match($regExps[$regExpType], $row[$colName], $matches);
-
-                        $row[$colName] = $matches[1] . ($matches[2] + $size) . ('middle' ==
-                            $regExpType ? $matches[3] : '');
-                    }
-                }
-                $writer->writeRow($row);
-            }
-            $size *= 2;
-        }
-    }
-
     /**
      * Move uploaded file and create source adapter instance.
      *
@@ -635,12 +566,12 @@ class Import extends \Magento\ImportExport\Model\AbstractModel
      */
     public function invalidateIndex()
     {
-        if (!isset(self::$_entityInvalidatedIndexes[$this->getEntity()])) {
+        $relatedIndexers = $this->_importConfig->getRelatedIndexers($this->getEntity());
+        if (empty($relatedIndexers)) {
             return $this;
         }
 
-        $indexers = self::$_entityInvalidatedIndexes[$this->getEntity()];
-        foreach ($indexers as $indexer) {
+        foreach ($relatedIndexers as $indexer) {
             $indexProcess = $this->_indexer->getProcessByCode($indexer);
             if ($indexProcess) {
                 $indexProcess->changeStatus(\Magento\Index\Model\Process::STATUS_REQUIRE_REINDEX);
diff --git a/app/code/Magento/ImportExport/Model/Import/Config.php b/app/code/Magento/ImportExport/Model/Import/Config.php
index 1628e3a76b5..d10c5715932 100644
--- a/app/code/Magento/ImportExport/Model/Import/Config.php
+++ b/app/code/Magento/ImportExport/Model/Import/Config.php
@@ -49,12 +49,26 @@ class Config extends \Magento\Framework\Config\Data implements \Magento\ImportEx
     }
 
     /**
-     * Retrieve import product types configuration
+     * Retrieve import entity types configuration
      *
+     * @param string $entity
      * @return array
      */
-    public function getProductTypes()
+    public function getEntityTypes($entity)
     {
-        return $this->get('productTypes');
+        $entities = $this->getEntities();
+        return isset($entities[$entity]) ? $entities[$entity]['types'] : [];
+    }
+
+    /**
+     * Retrieve a list of indexes which are affected by import of the specified entity.
+     *
+     * @param string $entity
+     * @return array
+     */
+    public function getRelatedIndexers($entity)
+    {
+        $entities = $this->getEntities();
+        return isset($entities[$entity]) ? $entities[$entity]['relatedIndexers'] : [];
     }
 }
diff --git a/app/code/Magento/ImportExport/Model/Import/Config/Converter.php b/app/code/Magento/ImportExport/Model/Import/Config/Converter.php
index ee029a69ba6..c70ef459578 100644
--- a/app/code/Magento/ImportExport/Model/Import/Config/Converter.php
+++ b/app/code/Magento/ImportExport/Model/Import/Config/Converter.php
@@ -34,10 +34,10 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
      */
     public function convert($source)
     {
-        $output = array('entities' => array(), 'productTypes' => array());
-        /** @var \DOMNodeList $events */
+        $output = array('entities' => array());
+        /** @var \DOMNodeList $entities */
         $entities = $source->getElementsByTagName('entity');
-        /** @var DOMNode $entityConfig */
+        /** @var \DOMNode $entityConfig */
         foreach ($entities as $entityConfig) {
             $attributes = $entityConfig->attributes;
             $name = $attributes->getNamedItem('name')->nodeValue;
@@ -49,19 +49,37 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
                 'name' => $name,
                 'label' => $label,
                 'behaviorModel' => $behaviorModel,
-                'model' => $model
+                'model' => $model,
+                'types' => [],
+                'relatedIndexers' => []
             );
         }
 
-        /** @var \DOMNodeList $events */
-        $productTypes = $source->getElementsByTagName('productType');
-        /** @var DOMNode $productTypeConfig */
-        foreach ($productTypes as $productTypeConfig) {
-            $attributes = $productTypeConfig->attributes;
+        /** @var \DOMNodeList $entityTypes */
+        $entityTypes = $source->getElementsByTagName('entityType');
+        /** @var \DOMNode $entityTypeConfig */
+        foreach ($entityTypes as $entityTypeConfig) {
+            $attributes = $entityTypeConfig->attributes;
             $name = $attributes->getNamedItem('name')->nodeValue;
             $model = $attributes->getNamedItem('model')->nodeValue;
+            $entity = $attributes->getNamedItem('entity')->nodeValue;
 
-            $output['productTypes'][$name] = array('name' => $name, 'model' => $model);
+            if (isset($output['entities'][$entity])) {
+                $output['entities'][$entity]['types'][$name] = array('name' => $name, 'model' => $model);
+            }
+        }
+
+        /** @var \DOMNodeList $relatedIndexers */
+        $relatedIndexers = $source->getElementsByTagName('relatedIndexer');
+        /** @var \DOMNode $relatedIndexerConfig */
+        foreach ($relatedIndexers as $relatedIndexerConfig) {
+            $attributes = $relatedIndexerConfig->attributes;
+            $name = $attributes->getNamedItem('name')->nodeValue;
+            $entity = $attributes->getNamedItem('entity')->nodeValue;
+
+            if (isset($output['entities'][$entity])) {
+                $output['entities'][$entity]['relatedIndexers'][$name] = array('name' => $name);
+            }
         }
         return $output;
     }
diff --git a/app/code/Magento/ImportExport/Model/Import/Config/Reader.php b/app/code/Magento/ImportExport/Model/Import/Config/Reader.php
index c5ffde57603..473b8e20406 100644
--- a/app/code/Magento/ImportExport/Model/Import/Config/Reader.php
+++ b/app/code/Magento/ImportExport/Model/Import/Config/Reader.php
@@ -30,7 +30,11 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
      *
      * @var array
      */
-    protected $_idAttributes = array('/config/entity' => 'name', '/config/productType' => 'name');
+    protected $_idAttributes = array(
+        '/config/entity' => 'name',
+        '/config/entityType' => ['entity', 'name'],
+        '/config/relatedIndexers' => ['entity', 'name']
+    );
 
     /**
      * @param \Magento\Framework\Config\FileResolverInterface $fileResolver
diff --git a/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php b/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php
index b0e83ba0971..09412af615f 100644
--- a/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php
+++ b/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php
@@ -33,9 +33,18 @@ interface ConfigInterface
     public function getEntities();
 
     /**
-     * Retrieve import product types configuration
+     * Retrieve import entity types configuration
      *
+     * @param string $entity
      * @return array
      */
-    public function getProductTypes();
+    public function getEntityTypes($entity);
+
+    /**
+     * Retrieve a list of indexes which are affected by import of the specified entity.
+     *
+     * @param string $entity
+     * @return array
+     */
+    public function getRelatedIndexers($entity);
 }
diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
index a9c9a809ede..d538afdb5dc 100644
--- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
+++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php
@@ -310,7 +310,7 @@ abstract class AbstractEntity
     protected function _saveValidatedBunches()
     {
         $source = $this->_getSource();
-        $productDataSize = 0;
+        $currentDataSize = 0;
         $bunchRows = array();
         $startNewBunch = false;
         $nextRowBackup = array();
@@ -325,7 +325,7 @@ abstract class AbstractEntity
                 $this->_dataSourceModel->saveBunch($this->getEntityTypeCode(), $this->getBehavior(), $bunchRows);
 
                 $bunchRows = $nextRowBackup;
-                $productDataSize = strlen(serialize($bunchRows));
+                $currentDataSize = strlen(serialize($bunchRows));
                 $startNewBunch = false;
                 $nextRowBackup = array();
             }
@@ -345,12 +345,12 @@ abstract class AbstractEntity
 
                     $isBunchSizeExceeded = $bunchSize > 0 && count($bunchRows) >= $bunchSize;
 
-                    if ($productDataSize + $rowSize >= $maxDataSize || $isBunchSizeExceeded) {
+                    if ($currentDataSize + $rowSize >= $maxDataSize || $isBunchSizeExceeded) {
                         $startNewBunch = true;
                         $nextRowBackup = array($source->key() => $rowData);
                     } else {
                         $bunchRows[$source->key()] = $rowData;
-                        $productDataSize += $rowSize;
+                        $currentDataSize += $rowSize;
                     }
                 }
                 $source->next();
diff --git a/app/code/Magento/ImportExport/etc/di.xml b/app/code/Magento/ImportExport/etc/di.xml
index 0f22db67afc..9e68c41b716 100644
--- a/app/code/Magento/ImportExport/etc/di.xml
+++ b/app/code/Magento/ImportExport/etc/di.xml
@@ -26,7 +26,6 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
     <preference for="Magento\ImportExport\Model\Import\ConfigInterface" type="Magento\ImportExport\Model\Import\Config" />
     <preference for="Magento\ImportExport\Model\Export\ConfigInterface" type="Magento\ImportExport\Model\Export\Config" />
-    <preference for="Magento\ImportExport\Model\Export\RowCustomizerInterface" type="Magento\ImportExport\Model\Export\RowCustomizer\Composite" />
     <type name="Magento\Framework\Module\Setup\Migration">
         <arguments>
             <argument name="compositeModules" xsi:type="array">
diff --git a/app/code/Magento/ImportExport/etc/export.xsd b/app/code/Magento/ImportExport/etc/export.xsd
index 6f1cb2439ef..c55da5a826b 100644
--- a/app/code/Magento/ImportExport/etc/export.xsd
+++ b/app/code/Magento/ImportExport/etc/export.xsd
@@ -28,7 +28,7 @@
         <xs:complexType>
             <xs:choice maxOccurs="unbounded">
                 <xs:element name="entity" type="entityDeclaration" minOccurs="0" maxOccurs="unbounded" />
-                <xs:element name="productType" type="productTypeDeclaration" minOccurs="0" maxOccurs="unbounded" />
+                <xs:element name="entityType" type="entityTypeDeclaration" minOccurs="0" maxOccurs="unbounded" />
                 <xs:element name="fileFormat" type="fileFormatDeclaration" minOccurs="0" maxOccurs="unbounded" />
             </xs:choice>
         </xs:complexType>
@@ -41,15 +41,6 @@
             <xs:selector xpath="entity"/>
             <xs:field xpath="@name"/>
         </xs:unique>
-        <xs:unique name="uniqueProductTypeName">
-            <xs:annotation>
-                <xs:documentation>
-                    Export product type name must be unique.
-                </xs:documentation>
-            </xs:annotation>
-            <xs:selector xpath="productType"/>
-            <xs:field xpath="@name"/>
-        </xs:unique>
         <xs:unique name="uniqueFileFormatName">
             <xs:annotation>
                 <xs:documentation>
@@ -70,14 +61,16 @@
         <xs:attribute name="name" type="xs:string" use="required" />
         <xs:attribute name="label" type="xs:string" use="optional" />
         <xs:attribute name="model" type="modelName" use="optional" />
+        <xs:attribute name="entityAttributeFilterType" type="xs:string" use="required" />
     </xs:complexType>
 
-    <xs:complexType name="productTypeDeclaration">
+    <xs:complexType name="entityTypeDeclaration">
         <xs:annotation>
             <xs:documentation>
-                Export product type declaration.
+                Export entity type declaration.
             </xs:documentation>
         </xs:annotation>
+        <xs:attribute name="entity" type="xs:string" use="required" />
         <xs:attribute name="name" type="xs:string" use="required" />
         <xs:attribute name="model" type="modelName" use="required" />
     </xs:complexType>
diff --git a/app/code/Magento/ImportExport/etc/import.xsd b/app/code/Magento/ImportExport/etc/import.xsd
index d7986b3d927..ce78486632e 100644
--- a/app/code/Magento/ImportExport/etc/import.xsd
+++ b/app/code/Magento/ImportExport/etc/import.xsd
@@ -28,7 +28,8 @@
         <xs:complexType>
             <xs:choice maxOccurs="unbounded">
                 <xs:element name="entity" type="entityDeclaration" minOccurs="0" maxOccurs="unbounded" />
-                <xs:element name="productType" type="productTypeDeclaration" minOccurs="0" maxOccurs="unbounded" />
+                <xs:element name="entityType" type="entityTypeDeclaration" minOccurs="0" maxOccurs="unbounded" />
+                <xs:element name="relatedIndexer" type="relatedIndexerDeclaration" minOccurs="0" maxOccurs="unbounded" />
             </xs:choice>
         </xs:complexType>
         <xs:unique name="uniqueEntityName">
@@ -40,15 +41,6 @@
             <xs:selector xpath="entity"/>
             <xs:field xpath="@name"/>
         </xs:unique>
-        <xs:unique name="uniqueProductTypeName">
-            <xs:annotation>
-                <xs:documentation>
-                    Import product type name must be unique.
-                </xs:documentation>
-            </xs:annotation>
-            <xs:selector xpath="productType"/>
-            <xs:field xpath="@name"/>
-        </xs:unique>
     </xs:element>
 
     <xs:complexType name="entityDeclaration">
@@ -63,16 +55,27 @@
         <xs:attribute name="behaviorModel" type="modelName" use="optional" />
     </xs:complexType>
 
-    <xs:complexType name="productTypeDeclaration">
+    <xs:complexType name="entityTypeDeclaration">
         <xs:annotation>
             <xs:documentation>
-                Import product type declaration.
+                Import entity type declaration.
             </xs:documentation>
         </xs:annotation>
+        <xs:attribute name="entity" type="xs:string" use="required" />
         <xs:attribute name="name" type="xs:string" use="required" />
         <xs:attribute name="model" type="modelName" use="required" />
     </xs:complexType>
 
+    <xs:complexType name="relatedIndexerDeclaration">
+        <xs:annotation>
+            <xs:documentation>
+                Related index type declaration.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="entity" type="xs:string" use="required" />
+        <xs:attribute name="name" type="xs:string" use="required" />
+    </xs:complexType>
+
     <xs:simpleType name="modelName">
         <xs:annotation>
             <xs:documentation>
diff --git a/app/code/Magento/ImportExport/etc/module.xml b/app/code/Magento/ImportExport/etc/module.xml
index 620e9e97847..79e5ba267a3 100644
--- a/app/code/Magento/ImportExport/etc/module.xml
+++ b/app/code/Magento/ImportExport/etc/module.xml
@@ -24,19 +24,13 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_ImportExport" version="1.6.0.4" active="true">
-        <sequence>
-            <module name="Magento_Catalog"/>
-        </sequence>
+    <module name="Magento_ImportExport" schema_version="1.6.0.4" active="true">
         <depends>
             <module name="Magento_Store"/>
-            <module name="Magento_Catalog"/>
             <module name="Magento_Core"/>
             <module name="Magento_Backend"/>
             <module name="Magento_Eav"/>
             <module name="Magento_Index"/>
-            <module name="Magento_CatalogInventory"/>
-            <module name="Magento_Customer"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/ImportExport/i18n/de_DE.csv b/app/code/Magento/ImportExport/i18n/de_DE.csv
index 81144bd120f..9cb478aa704 100644
--- a/app/code/Magento/ImportExport/i18n/de_DE.csv
+++ b/app/code/Magento/ImportExport/i18n/de_DE.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Entitätenattribute"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entity-Adapter-Objekt muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein"
 "Entity is unknown","Entity ist unbekannt"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entity-Modelltyp muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein"
 "Error in data structure: behaviors are mixed","Fehler in der Datenstruktur: Vorgehensweisen sind unterschiedlich"
 "Error in data structure: entity codes are mixed","Fehler in der Datenstruktur: Entity-Codes sind unterschiedlich"
 "Export","Export"
diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv
index 0a40a1c4e69..962df32c6e5 100644
--- a/app/code/Magento/ImportExport/i18n/en_US.csv
+++ b/app/code/Magento/ImportExport/i18n/en_US.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Entity Attributes"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract"
 "Entity is unknown","Entity is unknown"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract"
 "Error in data structure: behaviors are mixed","Error in data structure: behaviors are mixed"
 "Error in data structure: entity codes are mixed","Error in data structure: entity codes are mixed"
 "Export","Export"
diff --git a/app/code/Magento/ImportExport/i18n/es_ES.csv b/app/code/Magento/ImportExport/i18n/es_ES.csv
index dcb5a99694f..eec75a789d9 100644
--- a/app/code/Magento/ImportExport/i18n/es_ES.csv
+++ b/app/code/Magento/ImportExport/i18n/es_ES.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Atributos de la Entidad"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","El objeto de adaptador de entidad debe ser una instancia de \Magento\ImportExport\Model\Import\Entity\Abstract"
 "Entity is unknown","Entidad desconocida"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","El modelo de tipo de entidad debe ser una instancia de \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract"
 "Error in data structure: behaviors are mixed","Error en la estructura de datos: hay conductas mezcladas"
 "Error in data structure: entity codes are mixed","Error en la estructura de datos: hay códigos de entidad mezclados"
 "Export","Exportar"
diff --git a/app/code/Magento/ImportExport/i18n/fr_FR.csv b/app/code/Magento/ImportExport/i18n/fr_FR.csv
index 8173cf0a379..0d1bdd15ff4 100644
--- a/app/code/Magento/ImportExport/i18n/fr_FR.csv
+++ b/app/code/Magento/ImportExport/i18n/fr_FR.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Attributs de l'entité"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","L'objet adaptateur doit être une isntance de \Magento\ImportExport\Model\Import\Entity\Abstract"
 "Entity is unknown","Entitée inconnue"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\ImportExport\Model\Import\Entity\Abstract"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Le type de modèle de l'entité doit être une instance de \Magento\ImportExport\Model\Import\Entity\Abstract"
 "Error in data structure: behaviors are mixed","Erreur dans la structure des données : les comportements sont mélangés"
 "Error in data structure: entity codes are mixed","Erreur dans la structure des données : les codes d'entité sont mélangés"
 "Export","Exporter"
diff --git a/app/code/Magento/ImportExport/i18n/nl_NL.csv b/app/code/Magento/ImportExport/i18n/nl_NL.csv
index 7ecd0054329..1e1dc6c99f6 100644
--- a/app/code/Magento/ImportExport/i18n/nl_NL.csv
+++ b/app/code/Magento/ImportExport/i18n/nl_NL.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Eenheidattributen"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entiteit adapterobject moet een instantie zijn van Magento_ImportExport_model_Import_Entity_Abstract"
 "Entity is unknown","Entiteit is onbekend"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\ImportExport\Model\Export_Entiteit_Product_Type_Abstract"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entiteit type model moet een instantie zijn van \Magento\ImportExport\Model\Import_Entiteit_Product_Type_Abstract"
 "Error in data structure: behaviors are mixed","Fout in datastructuur: gedragingen zijn gemengd"
 "Error in data structure: entity codes are mixed","Fout in datastructuur: entiteitcodes zijn gemengd"
 "Export","Export"
diff --git a/app/code/Magento/ImportExport/i18n/pt_BR.csv b/app/code/Magento/ImportExport/i18n/pt_BR.csv
index 30cb1021840..adfeda3cb84 100644
--- a/app/code/Magento/ImportExport/i18n/pt_BR.csv
+++ b/app/code/Magento/ImportExport/i18n/pt_BR.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","Atributos da entidade"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Objeto adaptador da entidade deve ser uma instância de \Magento\ImportExport\Model\Import\Entity\Abstract"
 "Entity is unknown","Entidade desconhecida"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Modelo de tipo de entidade deve ser uma instância de \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract"
 "Error in data structure: behaviors are mixed","Erro na estrutura de dados: os comportamentos estão misturados"
 "Error in data structure: entity codes are mixed","Erro na estrutura de dados: os códigos de entidade estão misturados"
 "Export","Exportar"
diff --git a/app/code/Magento/ImportExport/i18n/zh_CN.csv b/app/code/Magento/ImportExport/i18n/zh_CN.csv
index eb832ccb3b7..bed37847c22 100644
--- a/app/code/Magento/ImportExport/i18n/zh_CN.csv
+++ b/app/code/Magento/ImportExport/i18n/zh_CN.csv
@@ -17,8 +17,6 @@
 "Entity Attributes","编辑属性"
 "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","实体适配器对象必须为\Magento\ImportExport\Model\Import\Entity\Abstract的实例"
 "Entity is unknown","未知实体"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","实体类型模块必须为\Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType的实例"
-"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","实体类型模块必须为\Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract的实例"
 "Error in data structure: behaviors are mixed","数据结构有误:行为是混合的"
 "Error in data structure: entity codes are mixed","数据结构有误:实体代码是混合的"
 "Export","导出"
diff --git a/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php b/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php
index db778d4a174..f3e44457129 100644
--- a/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php
+++ b/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php
@@ -60,42 +60,4 @@ $table = $installer->getConnection()->newTable(
 );
 $installer->getConnection()->createTable($table);
 
-/**
- * Add unique key for 'catalog_product_link_attribute_int' table
- */
-$installer->getConnection()->addIndex(
-    $installer->getTable('catalog_product_link_attribute_int'),
-    $installer->getIdxName(
-        'catalog_product_link_attribute_int',
-        array('product_link_attribute_id', 'link_id'),
-        \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
-    ),
-    array('product_link_attribute_id', 'link_id'),
-    \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
-);
-
-/**
- * Add foreign keys for 'catalog_product_link_attribute_int' table
- */
-$installer->getConnection()->addForeignKey(
-    $installer->getFkName('catalog_product_link_attribute_int', 'link_id', 'catalog_product_link', 'link_id'),
-    $installer->getTable('catalog_product_link_attribute_int'),
-    'link_id',
-    $installer->getTable('catalog_product_link'),
-    'link_id'
-);
-
-$installer->getConnection()->addForeignKey(
-    $installer->getFkName(
-        'catalog_product_link_attribute_int',
-        'product_link_attribute_id',
-        'catalog_product_link_attribute',
-        'product_link_attribute_id'
-    ),
-    $installer->getTable('catalog_product_link_attribute_int'),
-    'product_link_attribute_id',
-    $installer->getTable('catalog_product_link_attribute'),
-    'product_link_attribute_id'
-);
-
 $installer->endSetup();
diff --git a/app/code/Magento/Index/etc/module.xml b/app/code/Magento/Index/etc/module.xml
index 7adaab6cadc..8ff8a9e206d 100644
--- a/app/code/Magento/Index/etc/module.xml
+++ b/app/code/Magento/Index/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Index" version="1.6.0.0" active="true">
+    <module name="Magento_Index" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Indexer/etc/module.xml b/app/code/Magento/Indexer/etc/module.xml
index 22eadde60c5..6e4005bd526 100644
--- a/app/code/Magento/Indexer/etc/module.xml
+++ b/app/code/Magento/Indexer/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Indexer" version="1.0.0.0" active="true">
+    <module name="Magento_Indexer" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Install/etc/module.xml b/app/code/Magento/Install/etc/module.xml
index 45e9608efdf..bb2fd20c81d 100644
--- a/app/code/Magento/Install/etc/module.xml
+++ b/app/code/Magento/Install/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Install" version="0.7.0" active="true">
+    <module name="Magento_Install" schema_version="0.7.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php
new file mode 100644
index 00000000000..2e270d68ff8
--- /dev/null
+++ b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Integration\Block\Adminhtml\Widget\Grid\Column\Renderer;
+
+/**
+ * Integration Name Renderer
+ */
+class Name extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Text
+{
+    /**
+     * Render integration name.
+     *
+     * If integration endpoint URL is unsecure then add error message to integration name.
+     *
+     * @param \Magento\Framework\Object $row
+     * @return string
+     */
+    public function render(\Magento\Framework\Object $row)
+    {
+        $text = parent::render($row);
+        if (strpos($row->getEndpoint(), 'http:') === 0) {
+            $text .= '<span class="icon-error"><span>Integration not secure</span></span>';
+        }
+        return $text;
+    }
+}
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
index ec032ac7002..ab82118a0f7 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
@@ -26,7 +26,7 @@ namespace Magento\Integration\Controller\Adminhtml;
 use Magento\Backend\App\Action;
 use Magento\Integration\Block\Adminhtml\Integration\Edit\Tab\Info;
 use Magento\Integration\Exception as IntegrationException;
-use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService;
+use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService;
 use Magento\Integration\Model\Integration as IntegrationModel;
 
 /**
@@ -52,7 +52,7 @@ class Integration extends Action
     /** @var \Magento\Framework\Logger */
     protected $_logger;
 
-    /** @var \Magento\Integration\Service\IntegrationV1Interface */
+    /** @var \Magento\Integration\Service\V1\IntegrationInterface */
     private $_integrationService;
 
     /** @var IntegrationOauthService */
@@ -64,6 +64,9 @@ class Integration extends Action
     /** @var \Magento\Integration\Helper\Data */
     protected $_integrationData;
 
+    /** @var  \Magento\Integration\Model\Resource\Integration\Collection */
+    protected $_integrationCollection;
+
     /**
      * @var \Magento\Framework\Escaper
      */
@@ -73,21 +76,23 @@ class Integration extends Action
      * @param \Magento\Backend\App\Action\Context $context
      * @param \Magento\Framework\Registry $registry
      * @param \Magento\Framework\Logger $logger
-     * @param \Magento\Integration\Service\IntegrationV1Interface $integrationService
+     * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService
      * @param IntegrationOauthService $oauthService
      * @param \Magento\Core\Helper\Data $coreHelper
      * @param \Magento\Integration\Helper\Data $integrationData
      * @param \Magento\Framework\Escaper $escaper
+     * @param \Magento\Integration\Model\Resource\Integration\Collection $integrationCollection
      */
     public function __construct(
         \Magento\Backend\App\Action\Context $context,
         \Magento\Framework\Registry $registry,
         \Magento\Framework\Logger $logger,
-        \Magento\Integration\Service\IntegrationV1Interface $integrationService,
+        \Magento\Integration\Service\V1\IntegrationInterface $integrationService,
         IntegrationOauthService $oauthService,
         \Magento\Core\Helper\Data $coreHelper,
         \Magento\Integration\Helper\Data $integrationData,
-        \Magento\Framework\Escaper $escaper
+        \Magento\Framework\Escaper $escaper,
+        \Magento\Integration\Model\Resource\Integration\Collection $integrationCollection
     ) {
         parent::__construct($context);
         $this->_registry = $registry;
@@ -97,6 +102,7 @@ class Integration extends Action
         $this->_coreHelper = $coreHelper;
         $this->_integrationData = $integrationData;
         $this->escaper = $escaper;
+        $this->_integrationCollection = $integrationCollection;
         parent::__construct($context);
     }
 
@@ -107,6 +113,13 @@ class Integration extends Action
      */
     public function indexAction()
     {
+        $unsecureEndpointsCount = $this->_integrationCollection->addUnsecureEndpointFilter()->getSize();
+        if ($unsecureEndpointsCount > 0) {
+            // @codingStandardsIgnoreStart
+            $this->messageManager->addNotice(__('Warning! Integrations not using HTTPS are insecure and potentially expose private or personally identifiable information')
+            // @codingStandardsIgnoreEnd
+            );
+        }
         $this->_view->loadLayout();
         $this->_setActiveMenu('Magento_Integration::system_integrations');
         $this->_addBreadcrumb(__('Integrations'), __('Integrations'));
diff --git a/app/code/Magento/Integration/Controller/Token.php b/app/code/Magento/Integration/Controller/Token.php
index 8e954b18fb2..e3d368fe196 100644
--- a/app/code/Magento/Integration/Controller/Token.php
+++ b/app/code/Magento/Integration/Controller/Token.php
@@ -23,8 +23,8 @@
  */
 namespace Magento\Integration\Controller;
 
-use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService;
-use Magento\Integration\Service\IntegrationV1Interface as IntegrationService;
+use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService;
+use Magento\Integration\Service\V1\IntegrationInterface as IntegrationService;
 use Magento\Integration\Model\Integration as IntegrationModel;
 
 /**
diff --git a/app/code/Magento/Integration/Model/Manager.php b/app/code/Magento/Integration/Model/Manager.php
index f895f8f5405..c8331b8370d 100644
--- a/app/code/Magento/Integration/Model/Manager.php
+++ b/app/code/Magento/Integration/Model/Manager.php
@@ -35,7 +35,7 @@ class Manager
     /**
      * Integration service
      *
-     * @var \Magento\Integration\Service\IntegrationV1Interface
+     * @var \Magento\Integration\Service\V1\IntegrationInterface
      */
     protected $_integrationService;
 
@@ -48,11 +48,11 @@ class Manager
 
     /**
      * @param Config $integrationConfig
-     * @param \Magento\Integration\Service\IntegrationV1Interface $integrationService
+     * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService
      */
     public function __construct(
         Config $integrationConfig,
-        \Magento\Integration\Service\IntegrationV1Interface $integrationService
+        \Magento\Integration\Service\V1\IntegrationInterface $integrationService
     ) {
         $this->_integrationService = $integrationService;
         $this->_integrationConfig = $integrationConfig;
diff --git a/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php b/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php
index f825bbe6fcd..16a040f82b0 100644
--- a/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php
+++ b/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php
@@ -23,7 +23,6 @@
  */
 namespace Magento\Integration\Model\Oauth\Nonce;
 
-use Magento\Framework\Oauth\OauthInterface;
 use Magento\Framework\Oauth\ConsumerInterface;
 use Magento\Framework\Oauth\NonceGeneratorInterface;
 
@@ -96,9 +95,8 @@ class Generator implements NonceGeneratorInterface
         try {
             $timestamp = (int)$timestamp;
             if ($timestamp <= 0 || $timestamp > time() + self::TIME_DEVIATION) {
-                throw new \Magento\Framework\Oauth\Exception(
-                    __('Incorrect timestamp value in the oauth_timestamp parameter'),
-                    OauthInterface::ERR_TIMESTAMP_REFUSED
+                throw new \Magento\Framework\Oauth\OauthInputException(
+                    'Incorrect timestamp value in the oauth_timestamp parameter'
                 );
             }
 
@@ -107,8 +105,8 @@ class Generator implements NonceGeneratorInterface
 
             if ($nonceObj->getNonce()) {
                 throw new \Magento\Framework\Oauth\Exception(
-                    __('The nonce is already being used by the consumer with ID %1', $consumer->getId()),
-                    OauthInterface::ERR_NONCE_USED
+                    'The nonce is already being used by the consumer with ID %1',
+                    [$consumer->getId()]
                 );
             }
 
@@ -116,7 +114,7 @@ class Generator implements NonceGeneratorInterface
         } catch (\Magento\Framework\Oauth\Exception $exception) {
             throw $exception;
         } catch (\Exception $exception) {
-            throw new \Magento\Framework\Oauth\Exception(__('An error occurred validating the nonce'));
+            throw new \Magento\Framework\Oauth\Exception('An error occurred validating the nonce');
         }
     }
 }
diff --git a/app/code/Magento/Integration/Model/Oauth/Token.php b/app/code/Magento/Integration/Model/Oauth/Token.php
index 17031e0c466..67f2a3632d4 100644
--- a/app/code/Magento/Integration/Model/Oauth/Token.php
+++ b/app/code/Magento/Integration/Model/Oauth/Token.php
@@ -210,17 +210,17 @@ class Token extends \Magento\Framework\Model\AbstractModel
     public function authorize($userId, $userType)
     {
         if (!$this->getId() || !$this->getConsumerId()) {
-            throw new OauthException(__('Token is not ready to be authorized'));
+            throw new OauthException('Token is not ready to be authorized');
         }
         if ($this->getAuthorized()) {
-            throw new OauthException(__('Token is already authorized'));
+            throw new OauthException('Token is already authorized');
         }
         if (self::USER_TYPE_ADMIN == $userType) {
             $this->setAdminId($userId);
         } elseif (self::USER_TYPE_CUSTOMER == $userType) {
             $this->setCustomerId($userId);
         } else {
-            throw new OauthException(__('User type is unknown'));
+            throw new OauthException('User type is unknown');
         }
 
         $this->setVerifier($this->_oauthHelper->generateVerifier());
@@ -241,7 +241,7 @@ class Token extends \Magento\Framework\Model\AbstractModel
     public function convertToAccess()
     {
         if (self::TYPE_REQUEST != $this->getType()) {
-            throw new OauthException(__('Cannot convert to access token due to token is not request type'));
+            throw new OauthException('Cannot convert to access token due to token is not request type');
         }
 
         $this->setType(self::TYPE_ACCESS);
@@ -289,7 +289,7 @@ class Token extends \Magento\Framework\Model\AbstractModel
         } elseif ($this->getCustomerId()) {
             return self::USER_TYPE_CUSTOMER;
         } else {
-            throw new OauthException(__('User type is unknown'));
+            throw new OauthException('User type is unknown');
         }
     }
 
diff --git a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
index 80ae2077b05..8ca3ff82b52 100644
--- a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
+++ b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php
@@ -23,7 +23,6 @@
  */
 namespace Magento\Integration\Model\Oauth\Token;
 
-use Magento\Framework\Oauth\OauthInterface;
 use Magento\Framework\Oauth\TokenProviderInterface;
 
 class Provider implements TokenProviderInterface
@@ -76,8 +75,7 @@ class Provider implements TokenProviderInterface
         $expiry = $this->_dataHelper->getConsumerExpirationPeriod();
         if ($this->_date->timestamp() - $consumerTS > $expiry) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Consumer key has expired'),
-                OauthInterface::ERR_CONSUMER_KEY_INVALID
+                'Consumer key has expired'
             );
         }
         return true;
@@ -91,8 +89,7 @@ class Provider implements TokenProviderInterface
         $token = $this->getTokenByConsumerId($consumer->getId());
         if ($token->getType() != \Magento\Integration\Model\Oauth\Token::TYPE_VERIFIER) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Cannot create request token because consumer token is not a verifier token'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Cannot create request token because consumer token is not a verifier token'
             );
         }
         $requestToken = $token->createRequestToken($token->getId(), $consumer->getCallbackUrl());
@@ -108,8 +105,7 @@ class Provider implements TokenProviderInterface
 
         if (!$this->_isTokenAssociatedToConsumer($token, $consumer)) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Request token is not associated with the specified consumer'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Request token is not associated with the specified consumer'
             );
         }
 
@@ -117,8 +113,7 @@ class Provider implements TokenProviderInterface
         // In this flow (token flow) the token has to be of type "request" else its marked as reused.
         if (\Magento\Integration\Model\Oauth\Token::TYPE_REQUEST != $token->getType()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token is already being used'),
-                OauthInterface::ERR_TOKEN_USED
+                'Token is already being used'
             );
         }
 
@@ -136,7 +131,7 @@ class Provider implements TokenProviderInterface
         $token = $this->getTokenByConsumerId($consumer->getId());
         if (\Magento\Integration\Model\Oauth\Token::TYPE_REQUEST != $token->getType()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Cannot get access token because consumer token is not a request token')
+                'Cannot get access token because consumer token is not a request token'
             );
         }
         $accessToken = $token->convertToAccess();
@@ -152,20 +147,17 @@ class Provider implements TokenProviderInterface
 
         if (!$this->_isTokenAssociatedToConsumer($token, $consumer)) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token is not associated with the specified consumer'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Token is not associated with the specified consumer'
             );
         }
         if (\Magento\Integration\Model\Oauth\Token::TYPE_ACCESS != $token->getType()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token is not an access token'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Token is not an access token'
             );
         }
         if ($token->getRevoked()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Access token has been revoked'),
-                OauthInterface::ERR_TOKEN_REVOKED
+                'Access token has been revoked'
             );
         }
 
@@ -183,15 +175,13 @@ class Provider implements TokenProviderInterface
 
         if (\Magento\Integration\Model\Oauth\Token::TYPE_ACCESS != $token->getType()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token is not an access token'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Token is not an access token'
             );
         }
 
         if ($token->getRevoked()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Access token has been revoked'),
-                OauthInterface::ERR_TOKEN_REVOKED
+                'Access token has been revoked'
             );
         }
 
@@ -213,8 +203,7 @@ class Provider implements TokenProviderInterface
     {
         if (strlen($consumerKey) != \Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_KEY) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Consumer key is not the correct length'),
-                OauthInterface::ERR_CONSUMER_KEY_REJECTED
+                'Consumer key is not the correct length'
             );
         }
 
@@ -222,8 +211,7 @@ class Provider implements TokenProviderInterface
 
         if (!$consumer->getId()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('A consumer having the specified key does not exist'),
-                OauthInterface::ERR_CONSUMER_KEY_REJECTED
+                'A consumer having the specified key does not exist'
             );
         }
 
@@ -242,20 +230,17 @@ class Provider implements TokenProviderInterface
     {
         if (!is_string($oauthVerifier)) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Verifier is invalid'),
-                OauthInterface::ERR_VERIFIER_INVALID
+                'Verifier is invalid'
             );
         }
         if (!$this->validateOauthToken($oauthVerifier)) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Verifier is not the correct length'),
-                OauthInterface::ERR_VERIFIER_INVALID
+                'Verifier is not the correct length'
             );
         }
         if ($tokenVerifier != $oauthVerifier) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token verifier and verifier token do not match'),
-                OauthInterface::ERR_VERIFIER_INVALID
+                'Token verifier and verifier token do not match'
             );
         }
     }
@@ -273,8 +258,8 @@ class Provider implements TokenProviderInterface
 
         if (!$consumer->getId()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('A consumer with the ID %1 does not exist', $consumerId),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'A consumer with the ID %1 does not exist',
+                [$consumerId]
             );
         }
 
@@ -292,8 +277,7 @@ class Provider implements TokenProviderInterface
     {
         if (!$this->validateOauthToken($token)) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Token is not the correct length'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Token is not the correct length'
             );
         }
 
@@ -301,8 +285,7 @@ class Provider implements TokenProviderInterface
 
         if (!$tokenObj->getId()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Specified token does not exist'),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'Specified token does not exist'
             );
         }
 
@@ -322,8 +305,8 @@ class Provider implements TokenProviderInterface
 
         if (!$token->getId()) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('A token with consumer ID %1 does not exist', $consumerId),
-                OauthInterface::ERR_TOKEN_REJECTED
+                'A token with consumer ID %1 does not exist',
+                [$consumerId]
             );
         }
 
diff --git a/app/code/Magento/Integration/Model/Resource/Integration/Collection.php b/app/code/Magento/Integration/Model/Resource/Integration/Collection.php
index 837e9f132be..7000a98e044 100644
--- a/app/code/Magento/Integration/Model/Resource/Integration/Collection.php
+++ b/app/code/Magento/Integration/Model/Resource/Integration/Collection.php
@@ -37,4 +37,14 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac
     {
         $this->_init('Magento\Integration\Model\Integration', 'Magento\Integration\Model\Resource\Integration');
     }
+
+    /**
+     * Get unsecure enpoints
+     *
+     * @return $this
+     */
+    public function addUnsecureEndpointFilter()
+    {
+        return $this->addFieldToFilter('endpoint', ['like' => 'http:%']);
+    }
 }
diff --git a/app/code/Magento/Integration/Service/IntegrationV1.php b/app/code/Magento/Integration/Service/V1/Integration.php
similarity index 96%
rename from app/code/Magento/Integration/Service/IntegrationV1.php
rename to app/code/Magento/Integration/Service/V1/Integration.php
index b667f3827e9..9158e6de05f 100644
--- a/app/code/Magento/Integration/Service/IntegrationV1.php
+++ b/app/code/Magento/Integration/Service/V1/Integration.php
@@ -21,18 +21,18 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
 use Magento\Integration\Model\Integration\Factory as IntegrationFactory;
 use Magento\Integration\Model\Integration as IntegrationModel;
-use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService;
+use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService;
 
 /**
  * Integration Service.
  *
  * This service is used to interact with integrations.
  */
-class IntegrationV1 implements \Magento\Integration\Service\IntegrationV1Interface
+class Integration implements \Magento\Integration\Service\V1\IntegrationInterface
 {
     /**
      * @var IntegrationFactory
diff --git a/app/code/Magento/Integration/Service/IntegrationV1Interface.php b/app/code/Magento/Integration/Service/V1/IntegrationInterface.php
similarity index 96%
rename from app/code/Magento/Integration/Service/IntegrationV1Interface.php
rename to app/code/Magento/Integration/Service/V1/IntegrationInterface.php
index 1b8dfa4d0db..473d6926dd4 100644
--- a/app/code/Magento/Integration/Service/IntegrationV1Interface.php
+++ b/app/code/Magento/Integration/Service/V1/IntegrationInterface.php
@@ -21,14 +21,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
 use Magento\Integration\Model\Integration as IntegrationModel;
 
 /**
  * Integration Service Interface
  */
-interface IntegrationV1Interface
+interface IntegrationInterface
 {
     /**
      * Create a new Integration
diff --git a/app/code/Magento/Integration/Service/OauthV1.php b/app/code/Magento/Integration/Service/V1/Oauth.php
similarity index 95%
rename from app/code/Magento/Integration/Service/OauthV1.php
rename to app/code/Magento/Integration/Service/V1/Oauth.php
index acbcdc3037f..054de2b4013 100644
--- a/app/code/Magento/Integration/Service/OauthV1.php
+++ b/app/code/Magento/Integration/Service/V1/Oauth.php
@@ -21,9 +21,8 @@
  * @copyright  Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
-use Magento\Framework\Oauth\OauthInterface;
 use Magento\Integration\Model\Oauth\Token\Provider as TokenProvider;
 use Magento\Integration\Model\Oauth\Token;
 use Magento\Integration\Model\Oauth\Token\Factory as TokenFactory;
@@ -38,7 +37,7 @@ use Magento\Integration\Model\Oauth\Consumer as ConsumerModel;
  * TODO: Fix coupling between objects
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class OauthV1 implements OauthV1Interface
+class Oauth implements OauthInterface
 {
     /**
      * @var  \Magento\Store\Model\StoreManagerInterface
@@ -127,7 +126,7 @@ class OauthV1 implements OauthV1Interface
             throw $exception;
         } catch (\Exception $exception) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Unexpected error. Unable to create oAuth consumer account.')
+                'Unexpected error. Unable to create oAuth consumer account.'
             );
         }
     }
@@ -184,7 +183,7 @@ class OauthV1 implements OauthV1Interface
             throw $exception;
         } catch (\Exception $exception) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Unexpected error. Unable to load oAuth consumer account.')
+                'Unexpected error. Unable to load oAuth consumer account.'
             );
         }
     }
@@ -200,7 +199,7 @@ class OauthV1 implements OauthV1Interface
             throw $exception;
         } catch (\Exception $exception) {
             throw new \Magento\Framework\Oauth\Exception(
-                __('Unexpected error. Unable to load oAuth consumer account.')
+                'Unexpected error. Unable to load oAuth consumer account.'
             );
         }
     }
@@ -242,7 +241,7 @@ class OauthV1 implements OauthV1Interface
         } catch (\Exception $exception) {
             $this->_logger->logException($exception);
             throw new \Magento\Framework\Oauth\Exception(
-                __('Unable to post data to consumer due to an unexpected error')
+                'Unable to post data to consumer due to an unexpected error'
             );
         }
     }
diff --git a/app/code/Magento/Integration/Service/OauthV1Interface.php b/app/code/Magento/Integration/Service/V1/OauthInterface.php
similarity index 98%
rename from app/code/Magento/Integration/Service/OauthV1Interface.php
rename to app/code/Magento/Integration/Service/V1/OauthInterface.php
index 6731d4f030e..7a1859b1bd4 100644
--- a/app/code/Magento/Integration/Service/OauthV1Interface.php
+++ b/app/code/Magento/Integration/Service/V1/OauthInterface.php
@@ -21,14 +21,14 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
 use Magento\Integration\Model\Oauth\Token;
 
 /**
  * Integration oAuth Service Interface
  */
-interface OauthV1Interface
+interface OauthInterface
 {
     /**
      * Create a new consumer account.
diff --git a/app/code/Magento/Integration/etc/di.xml b/app/code/Magento/Integration/etc/di.xml
index 7b4ba5c7dec..1557064be5b 100644
--- a/app/code/Magento/Integration/etc/di.xml
+++ b/app/code/Magento/Integration/etc/di.xml
@@ -24,8 +24,8 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
-    <preference for="Magento\Integration\Service\IntegrationV1Interface" type="Magento\Integration\Service\IntegrationV1" />
-    <preference for="Magento\Integration\Service\OauthV1Interface" type="Magento\Integration\Service\OauthV1" />
+    <preference for="Magento\Integration\Service\V1\IntegrationInterface" type="Magento\Integration\Service\V1\Integration" />
+    <preference for="Magento\Integration\Service\V1\OauthInterface" type="Magento\Integration\Service\V1\Oauth" />
     <preference for="Magento\Framework\Oauth\ConsumerInterface" type="Magento\Integration\Model\Oauth\Consumer"/>
     <preference for="Magento\Framework\Oauth\NonceGeneratorInterface" type="Magento\Integration\Model\Oauth\Nonce\Generator"/>
     <preference for="Magento\Framework\Oauth\TokenProviderInterface" type="Magento\Integration\Model\Oauth\Token\Provider"/>
diff --git a/app/code/Magento/Integration/etc/module.xml b/app/code/Magento/Integration/etc/module.xml
index e25b38c846e..e16c617dce9 100644
--- a/app/code/Magento/Integration/etc/module.xml
+++ b/app/code/Magento/Integration/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Integration" version="1.0.0.2" active="true">
+    <module name="Magento_Integration" schema_version="1.0.0.2" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml
index 472b36bbb20..c738e2992d1 100644
--- a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml
+++ b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml
@@ -51,6 +51,7 @@
                         <argument name="type" xsi:type="string">text</argument>
                         <argument name="index" xsi:type="string">name</argument>
                         <argument name="id" xsi:type="string">name</argument>
+                        <argument name="renderer" xsi:type="string">Magento\Integration\Block\Adminhtml\Widget\Grid\Column\Renderer\Name</argument>
                         <argument name="escape" xsi:type="string">1</argument>
                     </arguments>
                 </block>
diff --git a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js
index 69157d6ca4d..e65a16b1385 100644
--- a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js
+++ b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js
@@ -300,6 +300,10 @@
                         // Get integration name either from current element or from neighbor column
                         var integrationName = $(ctx).attr('data-row-name')
                             || $(ctx).parents('tr').find('.col-name').html().trim();
+                        if (integrationName.indexOf('<span') > -1) {
+                            // Remove unsecure URL warning from popup window title if it is present
+                            integrationName = integrationName.substring(0, integrationName.indexOf('<span'));
+                        }
                     } catch (e) {
                         throw 'Unable to find integration name';
                     }
diff --git a/app/code/Magento/LayeredNavigation/etc/frontend/di.xml b/app/code/Magento/LayeredNavigation/etc/frontend/di.xml
index ca76a6d3713..2c7d2172fed 100644
--- a/app/code/Magento/LayeredNavigation/etc/frontend/di.xml
+++ b/app/code/Magento/LayeredNavigation/etc/frontend/di.xml
@@ -38,6 +38,13 @@
             <argument name="filterList" xsi:type="object">searchFilterList</argument>
         </arguments>
     </virtualType>
+    <virtualType name="Magento\LayeredNavigation\Block\Navigation\AdvancedSearch" type="Magento\LayeredNavigation\Block\Navigation">
+        <arguments>
+            <argument name="catalogLayer" xsi:type="object">Magento\CatalogSearch\Model\Layer\Advanced</argument>
+            <argument name="visibilityFlag" xsi:type="object">Magento\Catalog\Model\Layer\Search\AvailabilityFlag</argument>
+            <argument name="filterList" xsi:type="object">advancedSearchFilterList</argument>
+        </arguments>
+    </virtualType>
     <virtualType name="Magento\LayeredNavigation\Block\Navigation\State\Category" type="Magento\LayeredNavigation\Block\Navigation\State">
         <arguments>
             <argument name="catalogLayer" xsi:type="object">Magento\Catalog\Model\Layer\Category</argument>
@@ -48,4 +55,9 @@
             <argument name="catalogLayer" xsi:type="object">Magento\Catalog\Model\Layer\Search</argument>
         </arguments>
     </virtualType>
+    <virtualType name="Magento\LayeredNavigation\Block\Navigation\State\AdvancedSearch" type="Magento\LayeredNavigation\Block\Navigation\State">
+        <arguments>
+            <argument name="catalogLayer" xsi:type="object">Magento\CatalogSearch\Model\Layer\Advanced</argument>
+        </arguments>
+    </virtualType>
 </config>
diff --git a/app/code/Magento/LayeredNavigation/etc/module.xml b/app/code/Magento/LayeredNavigation/etc/module.xml
index c0aa7354459..b16e24563eb 100644
--- a/app/code/Magento/LayeredNavigation/etc/module.xml
+++ b/app/code/Magento/LayeredNavigation/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_LayeredNavigation" version="1.0.0.0" active="true">
+    <module name="Magento_LayeredNavigation" schema_version="1.0.0.0" active="true">
         <depends>
             <module name="Magento_Catalog"/>
             <module name="Magento_Backend"/>
diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml
new file mode 100644
index 00000000000..21260bcdc50
--- /dev/null
+++ b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceContainer name="left">
+        <block class="Magento\LayeredNavigation\Block\Navigation\AdvancedSearch" name="advanced.search.leftnav" before="-" template="layer/view.phtml">
+            <block class="Magento\LayeredNavigation\Block\Navigation\State\AdvancedSearch" name="advanced.search.navigation.state" as="state" />
+            <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="advanced.search.navigation.renderer" as="renderer" template="layer/filter.phtml"/>
+        </block>
+    </referenceContainer>
+</layout>
diff --git a/app/code/Magento/Log/etc/module.xml b/app/code/Magento/Log/etc/module.xml
index deeb8f6a6d1..f9ec0aeae87 100644
--- a/app/code/Magento/Log/etc/module.xml
+++ b/app/code/Magento/Log/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Log" version="1.6.0.0" active="true">
+    <module name="Magento_Log" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Multishipping/etc/module.xml b/app/code/Magento/Multishipping/etc/module.xml
index d9b44bf9785..31cfef37fe5 100644
--- a/app/code/Magento/Multishipping/etc/module.xml
+++ b/app/code/Magento/Multishipping/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Multishipping" version="2.0.0.0" active="true">
+    <module name="Magento_Multishipping" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Newsletter/etc/module.xml b/app/code/Magento/Newsletter/etc/module.xml
index 0ed329fcb42..3f4d2f1b350 100644
--- a/app/code/Magento/Newsletter/etc/module.xml
+++ b/app/code/Magento/Newsletter/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Newsletter" version="1.6.0.2" active="true">
+    <module name="Magento_Newsletter" schema_version="1.6.0.2" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/OfflinePayments/etc/module.xml b/app/code/Magento/OfflinePayments/etc/module.xml
index cecfda746ac..24f917885db 100644
--- a/app/code/Magento/OfflinePayments/etc/module.xml
+++ b/app/code/Magento/OfflinePayments/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_OfflinePayments" version="1.6.0.0" active="true">
+    <module name="Magento_OfflinePayments" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/OfflineShipping/etc/module.xml b/app/code/Magento/OfflineShipping/etc/module.xml
index a8fd8cafc29..bd98e5a2db5 100644
--- a/app/code/Magento/OfflineShipping/etc/module.xml
+++ b/app/code/Magento/OfflineShipping/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_OfflineShipping" version="2.0.0.0" active="true">
+    <module name="Magento_OfflineShipping" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Store"/>
             <module name="Magento_Sales"/>
diff --git a/app/code/Magento/Ogone/etc/module.xml b/app/code/Magento/Ogone/etc/module.xml
index 7858fceddce..d5a600a2aa7 100644
--- a/app/code/Magento/Ogone/etc/module.xml
+++ b/app/code/Magento/Ogone/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Ogone" version="1.6.0.0" active="true">
+    <module name="Magento_Ogone" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Sales"/>
             <module name="Magento_Payment"/>
diff --git a/app/code/Magento/PageCache/etc/module.xml b/app/code/Magento/PageCache/etc/module.xml
index 85eb07eae8c..4d3e6065287 100644
--- a/app/code/Magento/PageCache/etc/module.xml
+++ b/app/code/Magento/PageCache/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_PageCache" version="1.6.0.0" active="true">
+    <module name="Magento_PageCache" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php b/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php
index 585ae7c71a2..2e0e7357174 100644
--- a/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php
+++ b/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php
@@ -96,6 +96,9 @@ class Nvp extends \Magento\Paypal\Model\Api\Nvp
      * @param \Magento\Directory\Model\RegionFactory $regionFactory
      * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
      * @param \Magento\Directory\Model\CountryFactory $countryFactory
+     * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory
+     * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory
+     * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
      * @param \Magento\RecurringPayment\Model\QuoteImporter $quoteImporter
      * @param array $data
      */
@@ -106,6 +109,9 @@ class Nvp extends \Magento\Paypal\Model\Api\Nvp
         \Magento\Directory\Model\RegionFactory $regionFactory,
         \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
         \Magento\Directory\Model\CountryFactory $countryFactory,
+        \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory,
+        \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory,
+        \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
         \Magento\RecurringPayment\Model\QuoteImporter $quoteImporter,
         array $data = array()
     ) {
@@ -116,6 +122,9 @@ class Nvp extends \Magento\Paypal\Model\Api\Nvp
             $regionFactory,
             $logAdapterFactory,
             $countryFactory,
+            $processableExceptionFactory,
+            $frameworkExceptionFactory,
+            $curlFactory,
             $data
         );
         $this->_quoteImporter = $quoteImporter;
diff --git a/app/code/Magento/PayPalRecurringPayment/etc/module.xml b/app/code/Magento/PayPalRecurringPayment/etc/module.xml
index 8f0cd9b74a6..1a7957cf93b 100644
--- a/app/code/Magento/PayPalRecurringPayment/etc/module.xml
+++ b/app/code/Magento/PayPalRecurringPayment/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_PayPalRecurringPayment" version="1.0.0.0" active="true">
+    <module name="Magento_PayPalRecurringPayment" schema_version="1.0.0.0" active="true">
         <depends>
             <module name="Magento_Customer"/>
             <module name="Magento_Directory"/>
diff --git a/app/code/Magento/Payment/etc/module.xml b/app/code/Magento/Payment/etc/module.xml
index 59f19e657f1..08103caabef 100644
--- a/app/code/Magento/Payment/etc/module.xml
+++ b/app/code/Magento/Payment/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Payment" version="1.6.0.0" active="true">
+    <module name="Magento_Payment" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
index b980a401087..f1577d038db 100644
--- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
+++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
@@ -28,6 +28,11 @@ namespace Magento\Paypal\Block\Adminhtml\System\Config;
  */
 class ApiWizard extends \Magento\Backend\Block\System\Config\Form\Field
 {
+    /**
+     * Path to block template
+     */
+    const WIZARD_TEMPLATE = 'system/config/api_wizard.phtml';
+
     /**
      * Set template to itself
      *
@@ -37,7 +42,7 @@ class ApiWizard extends \Magento\Backend\Block\System\Config\Form\Field
     {
         parent::_prepareLayout();
         if (!$this->getTemplate()) {
-            $this->setTemplate('system/config/api_wizard.phtml');
+            $this->setTemplate(static::WIZARD_TEMPLATE);
         }
         return $this;
     }
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php
new file mode 100644
index 00000000000..96b1f2357a6
--- /dev/null
+++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Block\Adminhtml\System\Config;
+
+class BmlApiWizard extends ApiWizard
+{
+    /**
+     * Path to block template
+     */
+    const WIZARD_TEMPLATE = 'system/config/bml_api_wizard.phtml';
+
+    /**
+     * Get the button and scripts contents
+     *
+     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
+     * @return string
+     */
+    protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
+    {
+        $originalData = $element->getOriginalData();
+        $this->addData(
+            array(
+                'button_label' => __($originalData['button_label']),
+                'button_url' => $originalData['button_url'],
+                'html_id' => $element->getHtmlId(),
+            )
+        );
+        return $this->_toHtml();
+    }
+}
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php
index 03f52d5de07..c7a044c9b91 100644
--- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php
+++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php
@@ -252,6 +252,26 @@ class Location extends \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Ex
                         }
                         paypalConflictsObject.ecCheckAvailability();
                         paypalConflictsObject.sharePayflowEnabling(enabler, isEvent);
+                    },
+                    handleBmlEnabler: function(event) {
+                        required = Event.element(event);
+                        var bml = $(required).bmlEnabler;
+                        if (required.value == "1") {
+                            bml.value = "1";
+                        }
+                        paypalConflictsObject.toggleBmlEnabler(required);
+                    },
+
+                    toggleBmlEnabler: function(required) {
+                        var bml = $(required).bmlEnabler;
+                        if (!bml) {
+                            return;
+                        }
+                        if (required.value != "1") {
+                            bml.value = "0";
+                            $(bml).disable();
+                        }
+                        $(bml).requiresObj.indicateEnabled();
                     }
                 };
 
@@ -308,9 +328,19 @@ class Location extends \Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Ex
                         $(ecPayflowScopeElement).click();
                     }
                 }
+                $$(".paypal-bml").each(function(bmlEnabler) {
+                    $(bmlEnabler).classNames().each(function(className) {
+                        if (className.indexOf("requires-") !== -1) {
+                            var required = $(className.replace("requires-", ""));
+                            required.bmlEnabler = bmlEnabler;
+                            Event.observe(required, "change", paypalConflictsObject.handleBmlEnabler);
+                        }
+                    });
+                });
 
                 $$(".paypal-enabler").each(function(enablerElement) {
                     paypalConflictsObject.checkPaymentConflicts(enablerElement, "initial");
+                    paypalConflictsObject.toggleBmlEnabler(enablerElement);
                 });
                 if (paypalConflictsObject.isConflict || paypalConflictsObject.ecMissed) {
                     var notification = \'' .
diff --git a/app/code/Magento/Paypal/Block/Bml/Banners.php b/app/code/Magento/Paypal/Block/Bml/Banners.php
new file mode 100644
index 00000000000..96d29f791e9
--- /dev/null
+++ b/app/code/Magento/Paypal/Block/Bml/Banners.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Block\Bml;
+
+use Magento\Framework\View\Element\Template;
+use Magento\Paypal\Model\Config;
+
+class Banners extends Template
+{
+    /**
+     * @var string
+     */
+    protected $_section;
+
+    /**
+     * @var int
+     */
+    protected $_position;
+
+    /**
+     * @var \Magento\Paypal\Model\Config
+     */
+    protected $_paypalConfig;
+
+    /**
+     * @param Template\Context $context
+     * @param Config $paypalConfig
+     * @param array $data
+     */
+    public function __construct(
+        Template\Context $context,
+        Config $paypalConfig,
+        array $data = array()
+    ) {
+        $this->_section = isset($data['section']) ? (string)$data['section'] : '';
+        $this->_position = isset($data['position']) ? (int)$data['position'] : 0;
+        $this->_paypalConfig = $paypalConfig;
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * Disable block output if banner turned off or PublisherId is miss
+     *
+     * @return string
+     */
+    protected function _toHtml()
+    {
+        $publisherId = $this->_paypalConfig->getBmlPublisherId();
+        $display = $this->_paypalConfig->getBmlDisplay($this->_section);
+        $position = $this->_paypalConfig->getBmlPosition($this->_section);
+        if (!$publisherId || $display == 0 || $this->_position != $position) {
+            return '';
+        }
+        $this->setData('publisher_id', $publisherId);
+        $this->setData('size', $this->_paypalConfig->getBmlSize($this->_section));
+        return parent::_toHtml();
+    }
+}
diff --git a/app/code/Magento/Paypal/Block/Bml/Form.php b/app/code/Magento/Paypal/Block/Bml/Form.php
new file mode 100644
index 00000000000..e057f8fbb18
--- /dev/null
+++ b/app/code/Magento/Paypal/Block/Bml/Form.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Block\Bml;
+
+use Magento\Paypal\Block\Express;
+use Magento\Paypal\Model\Config;
+
+class Form extends Express\Form
+{
+    /**
+     * Payment method code
+     * @var string
+     */
+    protected $_methodCode = Config::METHOD_WPP_BML;
+
+    /**
+     * Set template and redirect message
+     *
+     * @return void
+     */
+    protected function _construct()
+    {
+        $this->_config = $this->_paypalConfigFactory->create()->setMethod($this->getMethodCode());
+        /** @var $mark \Magento\Framework\View\Element\Template */
+        $mark = $this->_getMarkTemplate();
+        $mark->setPaymentAcceptanceMarkHref(
+            'https://www.securecheckout.billmelater.com/paycapture-content/'
+            . 'fetch?hash=AU826TU8&content=/bmlweb/ppwpsiw.html'
+        )->setPaymentAcceptanceMarkSrc('https://www.paypalobjects.com/en_US/i/logo/logo_BMLPP_90x34.gif')
+            ->setPaymentWhatIs(__('See terms'));
+
+        $this->_initializeRedirectTemplateWithMark($mark);
+    }
+}
diff --git a/app/code/Magento/Paypal/Block/Bml/Shortcut.php b/app/code/Magento/Paypal/Block/Bml/Shortcut.php
new file mode 100644
index 00000000000..61d55a5c657
--- /dev/null
+++ b/app/code/Magento/Paypal/Block/Bml/Shortcut.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal\Block\Bml;
+
+use Magento\Catalog\Block as CatalogBlock;
+use Magento\Paypal\Helper\Shortcut\ValidatorInterface;
+
+class Shortcut extends \Magento\Framework\View\Element\Template implements CatalogBlock\ShortcutInterface
+{
+    /**
+     * Whether the block should be eventually rendered
+     *
+     * @var bool
+     */
+    protected $_shouldRender = true;
+
+    /**
+     * Payment method code
+     *
+     * @var string
+     */
+    private $_paymentMethodCode = '';
+
+    /**
+     * Shortcut alias
+     *
+     * @var string
+     */
+    private $_alias = '';
+
+    /**
+     * Start express action
+     *
+     * @var string
+     */
+    private $_startAction = '';
+
+    /**
+     * @var \Magento\Payment\Helper\Data
+     */
+    private $_paymentData;
+
+    /**
+     * @var \Magento\Framework\Math\Random
+     */
+    private $_mathRandom;
+
+    /**
+     * Bml method code
+     *
+     * @var string
+     */
+    private $_bmlMethodCode = '';
+
+    /**
+     * Shortcut image path
+     */
+    const SHORTCUT_IMAGE = 'https://www.paypalobjects.com/webstatic/en_US/btn/btn_bml_SM.png';
+
+    /**
+     * @var ValidatorInterface
+     */
+    private $_shortcutValidator;
+
+    /**
+     * @param \Magento\Framework\View\Element\Template\Context $context
+     * @param \Magento\Payment\Helper\Data $paymentData
+     * @param \Magento\Framework\Math\Random $mathRandom
+     * @param ValidatorInterface $shortcutValidator
+     * @param string $paymentMethodCode
+     * @param string $startAction
+     * @param string $alias
+     * @param string $bmlMethodCode
+     * @param array $data
+     */
+    public function __construct
+    (
+        \Magento\Framework\View\Element\Template\Context $context,
+        \Magento\Payment\Helper\Data $paymentData,
+        \Magento\Framework\Math\Random $mathRandom,
+        ValidatorInterface $shortcutValidator,
+        $paymentMethodCode,
+        $startAction,
+        $alias,
+        $bmlMethodCode,
+        array $data = array()
+    ) {
+        $this->_paymentData = $paymentData;
+        $this->_mathRandom = $mathRandom;
+        $this->_shortcutValidator = $shortcutValidator;
+
+        $this->_paymentMethodCode = $paymentMethodCode;
+        $this->_startAction = $startAction;
+        $this->_alias = $alias;
+        $this->_bmlMethodCode = $bmlMethodCode;
+        parent::__construct($context, $data);
+    }
+
+    /**
+     * @return \Magento\Framework\View\Element\AbstractBlock
+     */
+    protected function _beforeToHtml()
+    {
+        $result = parent::_beforeToHtml();
+        $isInCatalog = $this->getIsInCatalogProduct();
+        if (!$this->_shortcutValidator->validate($this->_paymentMethodCode, $isInCatalog)) {
+            $this->_shouldRender = false;
+            return $result;
+        }
+
+        /** @var \Magento\Paypal\Model\Express $method */
+        $method = $this->_paymentData->getMethodInstance($this->_bmlMethodCode);
+        if (!$method || !$method->isAvailable()) {
+            $this->_shouldRender = false;
+            return $result;
+        }
+
+        $this->setShortcutHtmlId($this->_mathRandom->getUniqueHash('ec_shortcut_bml_'))
+            ->setCheckoutUrl($this->getUrl($this->_startAction))
+            ->setImageUrl(self::SHORTCUT_IMAGE)
+            ->setAdditionalLinkImage(
+                [
+                    'href' => 'https://www.securecheckout.billmelater.com/paycapture-content/'
+                    . 'fetch?hash=AU826TU8&content=/bmlweb/ppwpsiw.html',
+                    'src' => 'https://www.paypalobjects.com/webstatic/en_US/btn/btn_bml_text.png'
+                ]
+            );
+
+        return $result;
+    }
+
+    /**
+     * Render the block if needed
+     *
+     * @return string
+     */
+    protected function _toHtml()
+    {
+        if (!$this->_shouldRender) {
+            return '';
+        }
+        return parent::_toHtml();
+    }
+
+    /**
+     * Check is "OR" label position before shortcut
+     *
+     * @return bool
+     */
+    public function isOrPositionBefore()
+    {
+        return $this->getShowOrPosition() == CatalogBlock\ShortcutButtons::POSITION_BEFORE;
+    }
+
+    /**
+     * Check is "OR" label position after shortcut
+     *
+     * @return bool
+     */
+    public function isOrPositionAfter()
+    {
+        return $this->getShowOrPosition() == CatalogBlock\ShortcutButtons::POSITION_AFTER;
+    }
+
+    /**
+     * Get shortcut alias
+     *
+     * @return string
+     */
+    public function getAlias()
+    {
+        return $this->_alias;
+    }
+}
diff --git a/app/code/Magento/Paypal/Block/Express/Review.php b/app/code/Magento/Paypal/Block/Express/Review.php
index 1f64895327e..bf3005b4035 100644
--- a/app/code/Magento/Paypal/Block/Express/Review.php
+++ b/app/code/Magento/Paypal/Block/Express/Review.php
@@ -240,8 +240,6 @@ class Review extends \Magento\Framework\View\Element\Template
     {
         $methodInstance = $this->_quote->getPayment()->getMethodInstance();
         $this->setPaymentMethodTitle($methodInstance->getTitle());
-        $this->setUpdateOrderSubmitUrl($this->getUrl("{$this->_controllerPath}/updateOrder"));
-        $this->setUpdateShippingMethodsUrl($this->getUrl("{$this->_controllerPath}/updateShippingMethods"));
 
         $this->setShippingRateRequired(true);
         if ($this->_quote->getIsVirtual()) {
@@ -263,11 +261,13 @@ class Review extends \Magento\Framework\View\Element\Template
                 }
             }
 
+            $canEditShippingAddress = $this->_quote->getMayEditShippingAddress() && $this->_quote->getPayment()
+                ->getAdditionalInformation(\Magento\Paypal\Model\Express\Checkout::PAYMENT_INFO_BUTTON) == 1;
             // misc shipping parameters
             $this->setShippingMethodSubmitUrl(
                 $this->getUrl("{$this->_controllerPath}/saveShippingMethod")
             )->setCanEditShippingAddress(
-                $this->_quote->getMayEditShippingAddress()
+                $canEditShippingAddress
             )->setCanEditShippingMethod(
                 $this->_quote->getMayEditShippingMethod()
             );
diff --git a/app/code/Magento/Paypal/Block/Express/Shortcut.php b/app/code/Magento/Paypal/Block/Express/Shortcut.php
index 8f508fad6de..86c0c87bc24 100644
--- a/app/code/Magento/Paypal/Block/Express/Shortcut.php
+++ b/app/code/Magento/Paypal/Block/Express/Shortcut.php
@@ -24,6 +24,7 @@
 namespace Magento\Paypal\Block\Express;
 
 use Magento\Catalog\Block as CatalogBlock;
+use Magento\Paypal\Helper\Shortcut\ValidatorInterface;
 
 /**
  * Paypal express checkout shortcut link
@@ -42,35 +43,28 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
      *
      * @var string
      */
-    protected $_paymentMethodCode = \Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS;
+    protected $_paymentMethodCode = '';
 
     /**
      * Start express action
      *
      * @var string
      */
-    protected $_startAction = 'paypal/express/start';
+    protected $_startAction = '';
 
     /**
      * Express checkout model factory name
      *
      * @var string
      */
-    protected $_checkoutType = 'Magento\Paypal\Model\Express\Checkout';
+    protected $_checkoutType = '';
 
     /**
-     * Core registry
+     * Shortcut alias
      *
-     * @var \Magento\Framework\Registry
-     */
-    protected $_registry;
-
-    /**
-     * Payment data
-     *
-     * @var \Magento\Payment\Helper\Data
+     * @var string
      */
-    protected $_paymentData;
+    protected $_alias = '';
 
     /**
      * Paypal data
@@ -79,11 +73,6 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
      */
     protected $_paypalData;
 
-    /**
-     * @var \Magento\Customer\Model\Session
-     */
-    protected $_customerSession;
-
     /**
      * @var \Magento\Paypal\Model\ConfigFactory
      */
@@ -102,12 +91,7 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
     /**
      * @var \Magento\Framework\Math\Random
      */
-    protected $mathRandom;
-
-    /**
-     * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface
-     */
-    protected $productTypeConfig;
+    protected $_mathRandom;
 
     /**
      * @var \Magento\Customer\Helper\Session\CurrentCustomer
@@ -119,46 +103,56 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
      */
     protected $_localeResolver;
 
+    /**
+     * @var ValidatorInterface
+     */
+    private $_shortcutValidator;
+
     /**
      * @param \Magento\Framework\View\Element\Template\Context $context
      * @param \Magento\Paypal\Helper\Data $paypalData
-     * @param \Magento\Payment\Helper\Data $paymentData
-     * @param \Magento\Framework\Registry $registry
-     * @param \Magento\Customer\Model\Session $customerSession
      * @param \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory
      * @param \Magento\Paypal\Model\Express\Checkout\Factory $checkoutFactory
      * @param \Magento\Framework\Math\Random $mathRandom
-     * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig
      * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer
      * @param \Magento\Framework\Locale\ResolverInterface $localeResolver
+     * @param ValidatorInterface $shortcutValidator
+     * @param string $paymentMethodCode
+     * @param string $startAction
+     * @param string $checkoutType
+     * @param string $alias
      * @param \Magento\Checkout\Model\Session $checkoutSession
      * @param array $data
      */
     public function __construct(
         \Magento\Framework\View\Element\Template\Context $context,
         \Magento\Paypal\Helper\Data $paypalData,
-        \Magento\Payment\Helper\Data $paymentData,
-        \Magento\Framework\Registry $registry,
-        \Magento\Customer\Model\Session $customerSession,
         \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory,
         \Magento\Paypal\Model\Express\Checkout\Factory $checkoutFactory,
         \Magento\Framework\Math\Random $mathRandom,
-        \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
         \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer,
         \Magento\Framework\Locale\ResolverInterface $localeResolver,
+        ValidatorInterface $shortcutValidator,
+        $paymentMethodCode,
+        $startAction,
+        $checkoutType,
+        $alias,
         \Magento\Checkout\Model\Session $checkoutSession = null,
         array $data = array()
     ) {
-        $this->_registry = $registry;
         $this->_paypalData = $paypalData;
-        $this->_paymentData = $paymentData;
-        $this->_customerSession = $customerSession;
         $this->_paypalConfigFactory = $paypalConfigFactory;
         $this->_checkoutSession = $checkoutSession;
         $this->_checkoutFactory = $checkoutFactory;
-        $this->mathRandom = $mathRandom;
-        $this->productTypeConfig = $productTypeConfig;
+        $this->_mathRandom = $mathRandom;
         $this->_localeResolver = $localeResolver;
+        $this->_shortcutValidator = $shortcutValidator;
+
+        $this->_paymentMethodCode = $paymentMethodCode;
+        $this->_startAction = $startAction;
+        $this->_checkoutType = $checkoutType;
+        $this->_alias = $alias;
+
         parent::__construct($context, $data);
         $this->_isScopePrivate = true;
         $this->currentCustomer = $currentCustomer;
@@ -170,48 +164,22 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
     protected function _beforeToHtml()
     {
         $result = parent::_beforeToHtml();
-        $params = array($this->_paymentMethodCode);
-        $config = $this->_paypalConfigFactory->create(array('params' => $params));
-        $isInCatalog = $this->getIsInCatalogProduct();
-        $quote = $isInCatalog || !$this->_checkoutSession ? null : $this->_checkoutSession->getQuote();
+        /** @var \Magento\Paypal\Model\Config $config */
+        $config = $this->_paypalConfigFactory->create();
+        $config->setMethod($this->_paymentMethodCode);
 
-        // check visibility on cart or product page
-        $context = $isInCatalog ? 'visible_on_product' : 'visible_on_cart';
-        if (!$config->getConfigValue($context)) {
-            $this->_shouldRender = false;
-            return $result;
-        }
+        $isInCatalog = $this->getIsInCatalogProduct();
 
-        if ($isInCatalog) {
-            // Show PayPal shortcut on a product view page only if product has nonzero price
-            /** @var $currentProduct \Magento\Catalog\Model\Product */
-            $currentProduct = $this->_registry->registry('current_product');
-            if (!is_null($currentProduct)) {
-                $productPrice = (double)$currentProduct->getFinalPrice();
-                if (empty($productPrice) && !$this->productTypeConfig->isProductSet($currentProduct->getTypeId())) {
-                    $this->_shouldRender = false;
-                    return $result;
-                }
-            }
-        }
-        // validate minimum quote amount and validate quote for zero grandtotal
-        if (null !== $quote && (!$quote->validateMinimumAmount() ||
-            !$quote->getGrandTotal() && !$quote->hasNominalItems())
-        ) {
+        if (!$this->_shortcutValidator->validate($this->_paymentMethodCode, $isInCatalog)) {
             $this->_shouldRender = false;
             return $result;
         }
 
-        // check payment method availability
-        $methodInstance = $this->_paymentData->getMethodInstance($this->_paymentMethodCode);
-        if (!$methodInstance || !$methodInstance->isAvailable($quote)) {
-            $this->_shouldRender = false;
-            return $result;
-        }
+        $quote = $isInCatalog || !$this->_checkoutSession ? null : $this->_checkoutSession->getQuote();
 
         // set misc data
         $this->setShortcutHtmlId(
-            $this->mathRandom->getUniqueHash('ec_shortcut_')
+            $this->_mathRandom->getUniqueHash('ec_shortcut_')
         )->setCheckoutUrl(
             $this->getUrl($this->_startAction)
         );
@@ -220,6 +188,7 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
         if ($isInCatalog || null === $quote) {
             $this->setImageUrl($config->getExpressCheckoutShortcutImageUrl($this->_localeResolver->getLocaleCode()));
         } else {
+            /**@todo refactor checkout model. Move getCheckoutShortcutImageUrl to helper or separate model */
             $parameters = array('params' => array('quote' => $quote, 'config' => $config));
             $checkoutModel = $this->_checkoutFactory->create($this->_checkoutType, $parameters);
             $this->setImageUrl($checkoutModel->getCheckoutShortcutImageUrl());
@@ -282,6 +251,6 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal
      */
     public function getAlias()
     {
-        return 'product.info.addtocart.paypal';
+        return $this->_alias;
     }
 }
diff --git a/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php b/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php
new file mode 100644
index 00000000000..ad152b7e398
--- /dev/null
+++ b/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal\Block\Payflow\Bml;
+
+use Magento\Paypal\Model\Config;
+
+/** @todo methodCode should be set in constructor, than this form should be eliminated */
+class Form extends \Magento\Paypal\Block\Bml\Form
+{
+    /**
+     * Payment method code
+     * @var string
+     */
+    protected $_methodCode = Config::METHOD_WPP_PE_BML;
+}
diff --git a/app/code/Magento/Paypal/Block/Standard/Form.php b/app/code/Magento/Paypal/Block/Standard/Form.php
index 111f282c8f0..aee7e737f4d 100644
--- a/app/code/Magento/Paypal/Block/Standard/Form.php
+++ b/app/code/Magento/Paypal/Block/Standard/Form.php
@@ -76,26 +76,15 @@ class Form extends \Magento\Payment\Block\Form
     protected function _construct()
     {
         $this->_config = $this->_paypalConfigFactory->create()->setMethod($this->getMethodCode());
-        /** @var $mark \Magento\Framework\View\Element\Template */
-        $mark = $this->_layout->createBlock('Magento\Framework\View\Element\Template');
-        $mark->setTemplate(
-            'Magento_Paypal::payment/mark.phtml'
-        )->setPaymentAcceptanceMarkHref(
+        $mark = $this->_getMarkTemplate();
+        $mark->setPaymentAcceptanceMarkHref(
             $this->_config->getPaymentMarkWhatIsPaypalUrl($this->_localeResolver)
         )->setPaymentAcceptanceMarkSrc(
             $this->_config->getPaymentMarkImageUrl($this->_localeResolver->getLocaleCode())
         );
+
         // known issue: code above will render only static mark image
-        $this->setTemplate(
-            'Magento_Paypal::payment/redirect.phtml'
-        )->setRedirectMessage(
-            __('You will be redirected to the PayPal website when you place an order.')
-        )->setMethodTitle(
-            // Output PayPal mark, omit title
-            ''
-        )->setMethodLabelAfterHtml(
-            $mark->toHtml()
-        );
+        $this->_initializeRedirectTemplateWithMark($mark);
         return parent::_construct();
     }
 
@@ -108,4 +97,39 @@ class Form extends \Magento\Payment\Block\Form
     {
         return $this->_methodCode;
     }
+
+    /**
+     * Get initialized mark template
+     *
+     * @return \Magento\Framework\View\Element\Template
+     */
+    protected function _getMarkTemplate()
+    {
+        /** @var $mark \Magento\Framework\View\Element\Template */
+        $mark = $this->_layout->createBlock('Magento\Framework\View\Element\Template');
+        $mark->setTemplate(
+            'Magento_Paypal::payment/mark.phtml'
+        );
+        return $mark;
+    }
+
+    /**
+     * Initializes redirect template and set mark
+     * @param \Magento\Framework\View\Element\Template $mark
+     *
+     * @return void
+     */
+    protected function _initializeRedirectTemplateWithMark(\Magento\Framework\View\Element\Template $mark)
+    {
+        $this->setTemplate(
+            'Magento_Paypal::payment/redirect.phtml'
+        )->setRedirectMessage(
+            __('You will be redirected to the PayPal website when you place an order.')
+        )->setMethodTitle(
+            // Output PayPal mark, omit title
+            ''
+        )->setMethodLabelAfterHtml(
+            $mark->toHtml()
+        );
+    }
 }
diff --git a/app/code/Magento/Paypal/Controller/Bml.php b/app/code/Magento/Paypal/Controller/Bml.php
new file mode 100644
index 00000000000..fe6c91bba4b
--- /dev/null
+++ b/app/code/Magento/Paypal/Controller/Bml.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal\Controller;
+
+class Bml extends \Magento\Framework\App\Action\Action
+{
+    /**
+     * Action for Bill Me Later checkout button (product view and shopping cart pages)
+     *
+     * @return void
+     */
+    public function startAction()
+    {
+        $this->_forward('start', 'payflowexpress', 'paypal', [
+                'bml' => 1,
+                'button' => $this->getRequest()->getParam('button')
+            ]);
+    }
+}
diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php
index 3c96bea4692..6a311d71dec 100644
--- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php
+++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php
@@ -26,6 +26,7 @@ namespace Magento\Paypal\Controller\Express;
 use Magento\Checkout\Model\Type\Onepage;
 use Magento\Framework\App\Action\Action as AppAction;
 use Magento\Checkout\Controller\Express\RedirectLoginInterface;
+use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException;
 
 /**
  * Abstract Express Checkout Controller
@@ -181,6 +182,9 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
                 $this->_checkout->setIsBillingAgreementRequested($isBaRequested);
             }
 
+            // Bill Me Later
+            $this->_checkout->setIsBml((bool)$this->getRequest()->getParam('bml'));
+
             // giropay
             $this->_checkout->prepareGiropayUrls(
                 $this->_url->getUrl('checkout/onepage/success'),
@@ -188,9 +192,11 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
                 $this->_url->getUrl('checkout/onepage/success')
             );
 
+            $button = (bool)$this->getRequest()->getParam(\Magento\Paypal\Model\Express\Checkout::PAYMENT_INFO_BUTTON);
             $token = $this->_checkout->start(
                 $this->_url->getUrl('*/*/return'),
-                $this->_url->getUrl('*/*/cancel')
+                $this->_url->getUrl('*/*/cancel'),
+                $button
             );
             $url = $this->_checkout->getRedirectUrl();
             if ($token && $url) {
@@ -268,10 +274,21 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
      */
     public function returnAction()
     {
+        if ($this->getRequest()->getParam('retry_authorization') == 'true'
+            && is_array($this->_getCheckoutSession()->getPaypalTransactionData())
+        ) {
+            $this->_forward('placeOrder');
+            return;
+        }
         try {
+            $this->_getCheckoutSession()->unsPaypalTransactionData();
             $this->_initCheckout();
             $this->_checkout->returnFromPaypal($this->_initToken());
-            $this->_redirect('*/*/review');
+            if ($this->_checkout->canSkipOrderReviewStep()) {
+                $this->_forward('placeOrder');
+            } else {
+                $this->_redirect('*/*/review');
+            }
             return;
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
@@ -386,7 +403,7 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
         } catch (\Exception $e) {
-            $this->messageManager->addError(__('We can\'t update Order data.'));
+            $this->messageManager->addError(__('We can\'t update shipping method.'));
             $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
         }
         $this->getResponse()->setBody(
@@ -394,41 +411,6 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
         );
     }
 
-    /**
-     * Update Order (combined action for ajax and regular request)
-     *
-     * @return void
-     */
-    public function updateOrderAction()
-    {
-        try {
-            $isAjax = $this->getRequest()->getParam('isAjax');
-            $this->_initCheckout();
-            $this->_checkout->updateOrder($this->getRequest()->getParams());
-            if ($isAjax) {
-                $this->_view->loadLayout('paypal_express_review_details');
-                $this->getResponse()->setBody(
-                    $this->_view->getLayout()->getBlock('root')->setQuote($this->_getQuote())->toHtml()
-                );
-                return;
-            }
-        } catch (\Magento\Framework\Model\Exception $e) {
-            $this->messageManager->addError($e->getMessage());
-        } catch (\Exception $e) {
-            $this->messageManager->addError(__('We can\'t update Order data.'));
-            $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
-        }
-        if ($isAjax) {
-            $this->getResponse()->setBody(
-                '<script type="text/javascript">window.location.href = '
-                . $this->_url->getUrl('*/*/review')
-                . ';</script>'
-            );
-        } else {
-            $this->_redirect('*/*/review');
-        }
-    }
-
     /**
      * Submit the order
      *
@@ -479,13 +461,75 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
             $this->_initToken(false); // no need in token anymore
             $this->_redirect('checkout/onepage/success');
             return;
+        } catch (ApiProcessableException $e) {
+            $this->_processPaypalApiError($e);
         } catch (\Magento\Framework\Model\Exception $e) {
             $this->messageManager->addError($e->getMessage());
+            $this->_redirect('*/*/review');
         } catch (\Exception $e) {
             $this->messageManager->addError(__('We can\'t place the order.'));
             $this->_objectManager->get('Magento\Framework\Logger')->logException($e);
+            $this->_redirect('*/*/review');
+        }
+    }
+
+    /**
+     * Process PayPal API's processable errors
+     *
+     * @param \Magento\Paypal\Model\Api\ProcessableException $exception
+     * @return void
+     */
+    protected function _processPaypalApiError($exception)
+    {
+        switch ($exception->getCode()) {
+            case ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED:
+            case ApiProcessableException::API_TRANSACTION_EXPIRED:
+                $this->getResponse()->setRedirect(
+                    $this->_getQuote()->getPayment()->getCheckoutRedirectUrl()
+                );
+                break;
+            case ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL:
+                $this->_redirectSameToken();
+                break;
+            case ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE:
+                if ($this->_config->getPaymentAction() == \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER) {
+                    $paypalTransactionData = $this->_getCheckoutSession()->getPaypalTransactionData();
+                    $this->getResponse()->setRedirect(
+                        $this->_config->getExpressCheckoutOrderUrl($paypalTransactionData['transaction_id'])
+                    );
+                } else {
+                    $this->_redirectSameToken();
+                }
+                break;
+            default:
+                $this->_redirectToCartAndShowError($exception->getUserMessage());
+                break;
         }
-        $this->_redirect('*/*/review');
+    }
+
+    /**
+     * Redirect customer back to PayPal with the same token
+     *
+     * @return void
+     */
+    protected function _redirectSameToken()
+    {
+        $token = $this->_initToken();
+        $this->getResponse()->setRedirect(
+            $this->_config->getExpressCheckoutStartUrl($token)
+        );
+    }
+
+    /**
+     * Redirect customer to shopping cart and show error message
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    protected function _redirectToCartAndShowError($errorMessage)
+    {
+        $this->messageManager->addError($errorMessage);
+        $this->_redirect('checkout/cart');
     }
 
     /**
@@ -494,7 +538,7 @@ abstract class AbstractExpress extends AppAction implements RedirectLoginInterfa
      * @return void
      * @throws \Magento\Framework\Model\Exception
      */
-    private function _initCheckout()
+    protected function _initCheckout()
     {
         $quote = $this->_getQuote();
         if (!$quote->hasItems() || $quote->getHasError()) {
diff --git a/app/code/Magento/Paypal/Controller/Payflowbml.php b/app/code/Magento/Paypal/Controller/Payflowbml.php
new file mode 100644
index 00000000000..9e165d8bcbc
--- /dev/null
+++ b/app/code/Magento/Paypal/Controller/Payflowbml.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal\Controller;
+
+class Payflowbml extends \Magento\Framework\App\Action\Action
+{
+    /**
+     * Action for Bill Me Later checkout button (product view and shopping cart pages)
+     *
+     * @return void
+     */
+    public function startAction()
+    {
+        $this->_forward('start', 'express', 'paypal', [
+                'bml' => 1,
+                'button' => $this->getRequest()->getParam('button')
+            ]);
+    }
+}
diff --git a/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php b/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php
new file mode 100644
index 00000000000..ccfd8445741
--- /dev/null
+++ b/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+class CheckoutValidator implements ValidatorInterface
+{
+    /**
+     * @var \Magento\Checkout\Model\Session
+     */
+    private $_checkoutSession;
+
+    /**
+     * @var \Magento\Payment\Helper\Data
+     */
+    private $_paymentData;
+
+    /**
+     * @var ShortcutCheckoutValidator
+     */
+    private $_shortcutValidator;
+
+    /**
+     * @param \Magento\Checkout\Model\Session $checkoutSession
+     * @param Validator $shortcutValidator
+     * @param \Magento\Payment\Helper\Data $paymentData
+     */
+    public function __construct(
+        \Magento\Checkout\Model\Session $checkoutSession,
+        Validator $shortcutValidator,
+        \Magento\Payment\Helper\Data $paymentData
+    ) {
+        $this->_checkoutSession = $checkoutSession;
+        $this->_paymentData = $paymentData;
+        $this->_shortcutValidator = $shortcutValidator;
+    }
+
+    /**
+     * Validates shortcut
+     *
+     * @param string $code
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function validate($code, $isInCatalog)
+    {
+        return $this->_shortcutValidator->isContextAvailable($code, $isInCatalog)
+            && $this->_shortcutValidator->isPriceOrSetAvailable($isInCatalog)
+            && $this->isMethodQuoteAvailable($code, $isInCatalog)
+            && $this->isQuoteSummaryValid($isInCatalog);
+    }
+
+    /**
+     * Сhecks payment method and quote availability
+     *
+     * @param string $paymentCode
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function isMethodQuoteAvailable($paymentCode, $isInCatalog)
+    {
+        $quote = $isInCatalog ? null : $this->_checkoutSession->getQuote();
+        // check payment method availability
+        /** @var \Magento\Payment\Model\Method\AbstractMethod $methodInstance */
+        $methodInstance = $this->_paymentData->getMethodInstance($paymentCode);
+        if (!$methodInstance || !$methodInstance->isAvailable($quote)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     *  Validates minimum quote amount and zero grand total
+     *
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function isQuoteSummaryValid($isInCatalog)
+    {
+        $quote = $isInCatalog ? null : $this->_checkoutSession->getQuote();
+        // validate minimum quote amount and validate quote for zero grandtotal
+        if (null !== $quote && (!$quote->validateMinimumAmount() ||
+            !$quote->getGrandTotal() && !$quote->hasNominalItems())
+        ) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/app/code/Magento/Paypal/Helper/Shortcut/Factory.php b/app/code/Magento/Paypal/Helper/Shortcut/Factory.php
new file mode 100644
index 00000000000..8aa148929f0
--- /dev/null
+++ b/app/code/Magento/Paypal/Helper/Shortcut/Factory.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+ 
+namespace Magento\Paypal\Helper\Shortcut;
+
+class Factory
+{
+    /**
+     * Default validator
+     */
+    const DEFAULT_VALIDATOR = 'Magento\Paypal\Helper\Shortcut\Validator';
+
+    /**
+     * Checkout validator
+     */
+    const CHECKOUT_VALIDATOR = 'Magento\Paypal\Helper\Shortcut\CheckoutValidator';
+
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $_objectManager;
+
+    /**
+     * @param \Magento\Framework\ObjectManager $objectManager
+     */
+    public function __construct(\Magento\Framework\ObjectManager $objectManager)
+    {
+        $this->_objectManager = $objectManager;
+    }
+
+    /**
+     * @param mixed $parameter
+     * @return \Magento\Paypal\Helper\Shortcut\ValidatorInterface
+     */
+    public function create($parameter = null)
+    {
+        $instanceName = self::DEFAULT_VALIDATOR;
+        if (is_object($parameter) && $parameter instanceof \Magento\Checkout\Model\Session) {
+            $instanceName = self::CHECKOUT_VALIDATOR;
+        }
+        return $this->_objectManager->create($instanceName);
+    }
+}
diff --git a/app/code/Magento/Paypal/Helper/Shortcut/Validator.php b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php
new file mode 100644
index 00000000000..fdcc4123181
--- /dev/null
+++ b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+class Validator implements ValidatorInterface
+{
+    /**
+     * @var \Magento\Paypal\Model\ConfigFactory
+     */
+    private $_paypalConfigFactory;
+
+    /**
+     * @var \Magento\Checkout\Model\Session
+     */
+    private $_checkoutSession;
+
+    /**
+     * @var \Magento\Framework\Registry
+     */
+    private $_registry;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface
+     */
+    private $_productTypeConfig;
+
+    /**
+     * @var \Magento\Payment\Helper\Data
+     */
+    private $_paymentData;
+
+    /**
+     * @param \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory
+     * @param \Magento\Framework\Registry $registry
+     * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig
+     * @param \Magento\Payment\Helper\Data $paymentData
+     */
+    public function __construct(
+        \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory,
+        \Magento\Framework\Registry $registry,
+        \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
+        \Magento\Payment\Helper\Data $paymentData
+    ) {
+        $this->_paypalConfigFactory = $paypalConfigFactory;
+        $this->_registry = $registry;
+        $this->_productTypeConfig = $productTypeConfig;
+        $this->_paymentData = $paymentData;
+    }
+
+    /**
+     * Validates shortcut
+     *
+     * @param string $code
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function validate($code, $isInCatalog)
+    {
+        return $this->isContextAvailable($code, $isInCatalog)
+            && $this->isPriceOrSetAvailable($isInCatalog)
+            && $this->isMethodAvailable($code);
+    }
+
+    /**
+     * Checks visibility of context (cart or product page)
+     *
+     * @param string $paymentCode Payment method code
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function isContextAvailable($paymentCode, $isInCatalog)
+    {
+        /** @var \Magento\Paypal\Model\Config $config */
+        $config = $this->_paypalConfigFactory->create();
+        $config->setMethod($paymentCode);
+
+        // check visibility on cart or product page
+        $context = $isInCatalog ? 'visible_on_product' : 'visible_on_cart';
+        if (!$config->getConfigValue($context)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check is product available depending on final price or type set(configurable)
+     *
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function isPriceOrSetAvailable($isInCatalog)
+    {
+        if ($isInCatalog) {
+            // Show PayPal shortcut on a product view page only if product has nonzero price
+            /** @var $currentProduct \Magento\Catalog\Model\Product */
+            $currentProduct = $this->_registry->registry('current_product');
+            if (!is_null($currentProduct)) {
+                $productPrice = (double)$currentProduct->getFinalPrice();
+                if (empty($productPrice) && !$this->_productTypeConfig->isProductSet($currentProduct->getTypeId())) {
+                    return  false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Сhecks payment method and quote availability
+     *
+     * @param string $paymentCode
+     * @return bool
+     */
+    public function isMethodAvailable($paymentCode)
+    {
+        // check payment method availability
+        /** @var \Magento\Payment\Model\Method\AbstractMethod $methodInstance */
+        $methodInstance = $this->_paymentData->getMethodInstance($paymentCode);
+        if (!$methodInstance || !$methodInstance->isAvailable()) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php b/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php
new file mode 100644
index 00000000000..faa70df0a45
--- /dev/null
+++ b/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+interface ValidatorInterface
+{
+    /**
+     * Validates shortcut
+     *
+     * @param string $code
+     * @param bool $isInCatalog
+     * @return bool
+     */
+    public function validate($code, $isInCatalog);
+}
diff --git a/app/code/Magento/Paypal/Model/Api/Nvp.php b/app/code/Magento/Paypal/Model/Api/Nvp.php
index 585541edfae..622f5969ea8 100644
--- a/app/code/Magento/Paypal/Model/Api/Nvp.php
+++ b/app/code/Magento/Paypal/Model/Api/Nvp.php
@@ -119,6 +119,7 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         'PAYFLOWCOLOR' => 'payflowcolor',
         'LOCALECODE' => 'locale_code',
         'PAL' => 'pal',
+        'USERSELECTEDFUNDINGSOURCE' => 'funding_source',
 
         // transaction info
         'TRANSACTIONID' => 'transaction_id',
@@ -274,7 +275,8 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         'ITEMAMT',
         'SHIPPINGAMT',
         'TAXAMT',
-        'REQBILLINGADDRESS'
+        'REQBILLINGADDRESS',
+        'USERSELECTEDFUNDINGSOURCE'
     );
 
     /**
@@ -753,6 +755,21 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
      */
     protected $_countryFactory;
 
+    /**
+     * @var \Magento\Paypal\Model\Api\ProcessableExceptionFactory
+     */
+    protected $_processableExceptionFactory;
+
+    /**
+     * @var \Magento\Framework\Model\ExceptionFactory
+     */
+    protected $_frameworkExceptionFactory;
+
+    /**
+     * @var \Magento\Framework\HTTP\Adapter\CurlFactory
+     */
+    protected $_curlFactory;
+
     /**
      * @param \Magento\Customer\Helper\Address $customerAddress
      * @param \Magento\Framework\Logger $logger
@@ -760,6 +777,9 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
      * @param \Magento\Directory\Model\RegionFactory $regionFactory
      * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
      * @param \Magento\Directory\Model\CountryFactory $countryFactory
+     * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory
+     * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory
+     * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
      * @param array $data
      */
     public function __construct(
@@ -769,10 +789,16 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         \Magento\Directory\Model\RegionFactory $regionFactory,
         \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
         \Magento\Directory\Model\CountryFactory $countryFactory,
+        \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory,
+        \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory,
+        \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
         array $data = array()
     ) {
         parent::__construct($customerAddress, $logger, $localeResolver, $regionFactory, $logAdapterFactory, $data);
         $this->_countryFactory = $countryFactory;
+        $this->_processableExceptionFactory = $processableExceptionFactory;
+        $this->_frameworkExceptionFactory = $frameworkExceptionFactory;
+        $this->_curlFactory = $curlFactory;
     }
 
     /**
@@ -1173,7 +1199,7 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         $debugData = array('url' => $this->getApiEndpoint(), $methodName => $request);
 
         try {
-            $http = new \Magento\Framework\HTTP\Adapter\Curl();
+            $http = $this->_curlFactory->create();
             $config = array('timeout' => 60, 'verifypeer' => $this->_config->getConfigValue('verifyPeer'));
             if ($this->getUseProxy()) {
                 $config['proxy'] = $this->getProxyHost() . ':' . $this->getProxyPort();
@@ -1253,46 +1279,100 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
      *
      * @param array $response
      * @return void
-     * @throws \Magento\Framework\Model\Exception
+     * @throws \Magento\Paypal\Model\Api\ProcessableException|\Magento\Framework\Model\Exception
      */
     protected function _handleCallErrors($response)
+    {
+        $errors = $this->_extractErrorsFromResponse($response);
+        if (empty($errors)) {
+            return;
+        }
+
+        $errorMessages = array();
+        foreach ($errors as $error) {
+            $errorMessages[] = $error['message'];
+            $this->_callErrors[] = $error['code'];
+        }
+        $errorMessages = implode(' ', $errorMessages);
+
+        $exceptionLogMessage = sprintf(
+            'PayPal NVP gateway errors: %s Correlation ID: %s. Version: %s.',
+            $errorMessages,
+            isset($response['CORRELATIONID']) ? $response['CORRELATIONID'] : '',
+            isset($response['VERSION']) ? $response['VERSION'] : ''
+        );
+
+        $exception = count($errors) == 1 && $this->_isProcessableError($errors[0]['code'])
+            ? $this->_processableExceptionFactory->create(
+                ['message' => $exceptionLogMessage, 'code' => $errors[0]['code']]
+            ) : $this->_frameworkExceptionFactory->create(
+                ['message' => $exceptionLogMessage, 'code' => 0]
+            );
+        $this->_logger->logException($exception);
+
+        $exception->setMessage(__('PayPal gateway has rejected request. %1', $errorMessages));
+
+        throw $exception;
+    }
+
+    /**
+     * Format error message from error code, short error message and long error message
+     *
+     * @param string $errorCode
+     * @param string $shortErrorMessage
+     * @param string $longErrorMessage
+     * @return string
+     */
+    protected function _formatErrorMessage($errorCode, $shortErrorMessage, $longErrorMessage)
+    {
+        $longErrorMessage  = preg_replace('/\.$/', '', $longErrorMessage);
+        $shortErrorMessage = preg_replace('/\.$/', '', $shortErrorMessage);
+
+        return $longErrorMessage ? sprintf('%s (#%s: %s).', $longErrorMessage, $errorCode, $shortErrorMessage)
+            : sprintf('#%s: %s.', $errorCode, $shortErrorMessage);
+    }
+
+    /**
+     * Check whether PayPal error can be processed
+     *
+     * @param int $errorCode
+     * @return bool
+     */
+    protected function _isProcessableError($errorCode)
+    {
+        $processableErrorsList = $this->getProcessableErrors();
+
+        if (!$processableErrorsList || !is_array($processableErrorsList)) {
+            return false;
+        }
+
+        return in_array($errorCode, $processableErrorsList);
+    }
+
+    /**
+     * Extract errors from PayPal's response and return them in array
+     *
+     * @param array $response
+     * @return array
+     */
+    protected function _extractErrorsFromResponse($response)
     {
         $errors = array();
+
         for ($i = 0; isset($response["L_ERRORCODE{$i}"]); $i++) {
-            $longMessage = isset(
-                $response["L_LONGMESSAGE{$i}"]
-            ) ? preg_replace(
-                '/\.$/',
-                '',
+            $errorCode = $response["L_ERRORCODE{$i}"];
+            $errorMessage = $this->_formatErrorMessage(
+                $errorCode,
+                $response["L_SHORTMESSAGE{$i}"],
                 $response["L_LONGMESSAGE{$i}"]
-            ) : '';
-            $shortMessage = preg_replace('/\.$/', '', $response["L_SHORTMESSAGE{$i}"]);
-            $errors[] = $longMessage ? sprintf(
-                '%s (#%s: %s).',
-                $longMessage,
-                $response["L_ERRORCODE{$i}"],
-                $shortMessage
-            ) : sprintf(
-                '#%s: %s.',
-                $response["L_ERRORCODE{$i}"],
-                $shortMessage
             );
-            $this->_callErrors[] = $response["L_ERRORCODE{$i}"];
-        }
-        if ($errors) {
-            $errors = implode(' ', $errors);
-            $e = new \Magento\Framework\Model\Exception(
-                sprintf(
-                    'PayPal NVP gateway errors: %s Correlation ID: %s. Version: %s.',
-                    $errors,
-                    isset($response['CORRELATIONID']) ? $response['CORRELATIONID'] : '',
-                    isset($response['VERSION']) ? $response['VERSION'] : ''
-                )
+            $errors[] = array (
+                'code' => $errorCode,
+                'message' => $errorMessage
             );
-            $this->_logger->logException($e);
-            $e->setMessage(__('The PayPal gateway has rejected this request. %1', $errors));
-            throw $e;
         }
+
+        return $errors;
     }
 
     /**
@@ -1403,21 +1483,7 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
             \Magento\Framework\Object\Mapper::accumulateByMap($data, $shippingAddress, $this->_shippingAddressMap);
             $this->_applyStreetAndRegionWorkarounds($shippingAddress);
             // PayPal doesn't provide detailed shipping name fields, so the name will be overwritten
-            $firstName = $data['SHIPTONAME'];
-            $lastName = null;
-            if (isset($data['FIRSTNAME']) && $data['LASTNAME']) {
-                $firstName = $data['FIRSTNAME'];
-                $lastName = $data['LASTNAME'];
-            }
-            $shippingAddress->addData(
-                array(
-                    'prefix' => null,
-                    'firstname' => $firstName,
-                    'middlename' => null,
-                    'lastname' => $lastName,
-                    'suffix' => null
-                )
-            );
+            $shippingAddress->addData(['firstname'  => $data['SHIPTONAME']]);
             $this->setExportedShippingAddress($shippingAddress);
         }
     }
diff --git a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
index 6450d5b29f4..7961ea26bb4 100644
--- a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
+++ b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php
@@ -153,7 +153,8 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'ECI' => 'centinel_eci',
         'XID' => 'centinel_xid',
         'VPAS' => 'centinel_vpas_result',
-        'ECISUBMITTED3DS' => 'centinel_eci_result'
+        'ECISUBMITTED3DS' => 'centinel_eci_result',
+        'USERSELECTEDFUNDINGSOURCE' => 'funding_source'
     );
 
     /**
@@ -264,7 +265,8 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         'HDRBORDERCOLOR',
         'HDRBACKCOLOR',
         'PAYFLOWCOLOR',
-        'LOCALECODE'
+        'LOCALECODE',
+        'USERSELECTEDFUNDINGSOURCE'
     );
 
     /**
@@ -448,6 +450,9 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
      * @param \Magento\Directory\Model\RegionFactory $regionFactory
      * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory
      * @param \Magento\Directory\Model\CountryFactory $countryFactory
+     * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory
+     * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory
+     * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
      * @param \Magento\Framework\Math\Random $mathRandom
      * @param array $data
      */
@@ -458,10 +463,12 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
         \Magento\Directory\Model\RegionFactory $regionFactory,
         \Magento\Framework\Logger\AdapterFactory $logAdapterFactory,
         \Magento\Directory\Model\CountryFactory $countryFactory,
+        \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory,
+        \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory,
+        \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
         \Magento\Framework\Math\Random $mathRandom,
         array $data = array()
     ) {
-        $this->mathRandom = $mathRandom;
         parent::__construct(
             $customerAddress,
             $logger,
@@ -469,8 +476,12 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp
             $regionFactory,
             $logAdapterFactory,
             $countryFactory,
+            $processableExceptionFactory,
+            $frameworkExceptionFactory,
+            $curlFactory,
             $data
         );
+        $this->mathRandom = $mathRandom;
     }
 
     /**
diff --git a/app/code/Magento/Paypal/Model/Api/ProcessableException.php b/app/code/Magento/Paypal/Model/Api/ProcessableException.php
new file mode 100644
index 00000000000..3fae6df966b
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/Api/ProcessableException.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Paypal\Model\Api;
+
+class ProcessableException extends \Magento\Framework\Model\Exception
+{
+    /**#@+
+     * Error code returned by PayPal
+     */
+    const API_INTERNAL_ERROR = 10001;
+    const API_UNABLE_PROCESS_PAYMENT_ERROR_CODE = 10417;
+    const API_MAX_PAYMENT_ATTEMPTS_EXCEEDED = 10416;
+    const API_UNABLE_TRANSACTION_COMPLETE = 10486;
+    const API_TRANSACTION_EXPIRED = 10411;
+    const API_DO_EXPRESS_CHECKOUT_FAIL = 10422;
+    const API_COUNTRY_FILTER_DECLINE = 10537;
+    const API_MAXIMUM_AMOUNT_FILTER_DECLINE = 10538;
+    const API_OTHER_FILTER_DECLINE = 10539;
+    /**#@-*/
+
+    /**
+     * Get error message which can be displayed to website user
+     *
+     * @return string
+     */
+    public function getUserMessage()
+    {
+        switch ($this->getCode()) {
+            case self::API_INTERNAL_ERROR:
+            case self::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE:
+                $message = __("I'm sorry - but we were not able to process your payment. Please try another payment method or contact us so we can assist you.");
+                break;
+            case self::API_COUNTRY_FILTER_DECLINE:
+            case self::API_MAXIMUM_AMOUNT_FILTER_DECLINE:
+            case self::API_OTHER_FILTER_DECLINE:
+                $message = __("I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you.");
+                break;
+            default:
+                $message = $this->getMessage();
+        }
+        return $message;
+    }
+}
diff --git a/app/code/Magento/Paypal/Model/Bml.php b/app/code/Magento/Paypal/Model/Bml.php
new file mode 100644
index 00000000000..7e08dd4d047
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/Bml.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model;
+
+class Bml extends Express
+{
+    /**
+     * Payment method code
+     * @var string
+     */
+    protected $_code  = Config::METHOD_WPP_BML;
+
+    /**
+     * Checkout payment form
+     * @var string
+     */
+    protected $_formBlockType = 'Magento\Paypal\Block\Bml\Form';
+
+    /**
+     * Checkout redirect URL getter for onepage checkout
+     *
+     * @return string
+     */
+    public function getCheckoutRedirectUrl()
+    {
+        return $this->_urlBuilder->getUrl('paypal/bml/start');
+    }
+}
diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php
index 9d62ad04439..20caf2cdf53 100644
--- a/app/code/Magento/Paypal/Model/Config.php
+++ b/app/code/Magento/Paypal/Model/Config.php
@@ -39,6 +39,11 @@ class Config
      */
     const METHOD_WPP_EXPRESS = 'paypal_express';
 
+    /**
+     * PayPal Bill Me Later - Express Checkout
+     */
+    const METHOD_WPP_BML = 'paypal_express_bml';
+
     /**
      * PayPal Website Payments Pro - Direct Payments
      */
@@ -49,6 +54,11 @@ class Config
      */
     const METHOD_WPP_PE_EXPRESS = 'payflow_express';
 
+    /**
+     * PayPal Bill Me Later - Express Checkout (Payflow Edition)
+     */
+    const METHOD_WPP_PE_BML = 'payflow_express_bml';
+
     /**
      * Payflow Pro Gateway
      */
@@ -168,6 +178,11 @@ class Config
 
     /**#@-*/
 
+    /**
+     * Config path for enabling/disabling order review step in express checkout
+     */
+    const XML_PATH_PAYPAL_EXPRESS_SKIP_ORDER_REVIEW_STEP_FLAG = 'payment/paypal_express/skip_order_review_step';
+
     /**
      * Default URL for centinel API (PayPal Direct)
      *
@@ -740,6 +755,12 @@ class Config
                     $result = true;
                 }
                 break;
+            case self::METHOD_WPP_BML:
+                // check for express payments dependence
+                if (!$this->isMethodActive(self::METHOD_WPP_EXPRESS)) {
+                    $result = false;
+                }
+                break;
             case self::METHOD_WPP_PE_EXPRESS:
                 // check for direct payments dependence
                 if ($this->isMethodActive(self::METHOD_PAYFLOWLINK)
@@ -749,6 +770,12 @@ class Config
                     $result = false;
                 }
                 break;
+            case self::METHOD_WPP_PE_BML:
+                // check for express payments dependence
+                if (!$this->isMethodActive(self::METHOD_WPP_PE_EXPRESS)) {
+                    $result = false;
+                }
+                break;
             case self::METHOD_BILLING_AGREEMENT:
                 $result = $this->isWppApiAvailabe();
                 break;
@@ -778,8 +805,6 @@ class Config
                 $this->_storeId
             );
             $value = $this->_prepareValue($underscored, $value);
-            $this->{$key} = $value;
-            $this->{$underscored} = $value;
             return $value;
         }
         return null;
@@ -832,13 +857,7 @@ class Config
      */
     public function getMerchantCountry()
     {
-        $countryCode = $this->_scopeConfig->getValue(
-            $this->_mapGeneralFieldset(
-                'merchant_country',
-                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
-                $this->_storeId
-            )
-        );
+        $countryCode = $this->_scopeConfig->getValue($this->_mapGeneralFieldset('merchant_country'));
         if (!$countryCode) {
             $countryCode = $this->_coreData->getDefaultCountry($this->_storeId);
         }
@@ -873,7 +892,12 @@ class Config
     public function getCountryMethods($countryCode = null)
     {
         $countryMethods = [
-            'other' => [self::METHOD_WPS, self::METHOD_WPP_EXPRESS, self::METHOD_BILLING_AGREEMENT],
+            'other' => [
+                self::METHOD_WPS,
+                self::METHOD_WPP_EXPRESS,
+                self::METHOD_BILLING_AGREEMENT,
+                self::METHOD_WPP_BML
+            ],
             'US' => [
                 self::METHOD_PAYFLOWADVANCED,
                 self::METHOD_WPP_DIRECT,
@@ -881,8 +905,10 @@ class Config
                 self::METHOD_PAYFLOWPRO,
                 self::METHOD_PAYFLOWLINK,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT,
-                self::METHOD_WPP_PE_EXPRESS
+                self::METHOD_WPP_PE_EXPRESS,
+                self::METHOD_WPP_PE_BML
             ],
             'CA' => [
                 self::METHOD_WPP_DIRECT,
@@ -890,14 +916,17 @@ class Config
                 self::METHOD_PAYFLOWPRO,
                 self::METHOD_PAYFLOWLINK,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT,
-                self::METHOD_WPP_PE_EXPRESS
+                self::METHOD_WPP_PE_EXPRESS,
+                self::METHOD_WPP_PE_BML
             ],
             'GB' => [
                 self::METHOD_WPP_DIRECT,
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'AU' => [
@@ -905,46 +934,54 @@ class Config
                 self::METHOD_PAYFLOWPRO,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'NZ' => [
                 self::METHOD_WPS,
                 self::METHOD_PAYFLOWPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'JP' => [
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'FR' => [
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'IT' => [
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'ES' => [
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'HK' => [
                 self::METHOD_WPS,
                 self::METHOD_HOSTEDPRO,
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ],
             'DE' => [
                 self::METHOD_WPP_EXPRESS,
+                self::METHOD_WPP_BML,
                 self::METHOD_BILLING_AGREEMENT
             ]
         ];
@@ -954,6 +991,40 @@ class Config
         return isset($countryMethods[$countryCode]) ? $countryMethods[$countryCode] : $countryMethods['other'];
     }
 
+    /**
+     * Return start url for PayPal Basic
+     *
+     * @param string $token
+     * @return string
+     */
+    public function getPayPalBasicStartUrl($token)
+    {
+        $params = array(
+            'cmd'   => '_express-checkout',
+            'token' => $token,
+        );
+
+        if ($this->isOrderReviewStepDisabled()) {
+            $params['useraction'] = 'commit';
+        }
+
+        return $this->getPaypalUrl($params);
+    }
+
+    /**
+     * Check whether order review step enabled in configuration
+     *
+     * @return bool
+     */
+    public function isOrderReviewStepDisabled()
+    {
+        return $this->_scopeConfig->getValue(
+            self::XML_PATH_PAYPAL_EXPRESS_SKIP_ORDER_REVIEW_STEP_FLAG,
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+    }
+
     /**
      * Get url for dispatching customer to express checkout start
      *
@@ -965,6 +1036,17 @@ class Config
         return $this->getPaypalUrl(array('cmd' => '_express-checkout', 'token' => $token));
     }
 
+    /**
+     * Get url for dispatching customer to checkout retrial
+     *
+     * @param string $orderId
+     * @return string
+     */
+    public function getExpressCheckoutOrderUrl($orderId)
+    {
+        return $this->getPaypalUrl(array('cmd' => '_express-checkout', 'order_id' => $orderId));
+    }
+
     /**
      * Get url that allows to edit checkout details on paypal side
      *
@@ -1219,22 +1301,15 @@ class Config
     /**
      * BN code getter
      *
-     * @param string|null $countryCode ISO 3166-1
      * @return string
      */
-    public function getBuildNotationCode($countryCode = null)
+    public function getBuildNotationCode()
     {
-        $product = 'WPP';
-        if ($this->_methodCode && isset($this->_buildNotationPPMap[$this->_methodCode])) {
-            $product = $this->_buildNotationPPMap[$this->_methodCode];
-        }
-        if (null === $countryCode) {
-            $countryCode = $this->_matchBnCountryCode($this->getMerchantCountry());
-        }
-        if ($countryCode) {
-            $countryCode = '_' . $countryCode;
-        }
-        return sprintf('Magento_Cart_%s%s', $product, $countryCode);
+        return $this->_scopeConfig->getValue(
+            'paypal/bncode',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
     }
 
     /**
@@ -1539,6 +1614,12 @@ class Config
             case self::METHOD_WPS:
                 $path = $this->_mapStandardFieldset($fieldName);
                 break;
+            case self::METHOD_WPP_BML:
+                $path = $this->_mapBmlFieldset($fieldName);
+                break;
+            case self::METHOD_WPP_PE_BML:
+                $path = $this->_mapBmlPayflowFieldset($fieldName);
+                break;
             case self::METHOD_WPP_EXPRESS:
             case self::METHOD_WPP_PE_EXPRESS:
                 $path = $this->_mapExpressFieldset($fieldName);
@@ -1555,6 +1636,7 @@ class Config
         if ($path === null) {
             switch ($this->_methodCode) {
                 case self::METHOD_WPP_EXPRESS:
+                case self::METHOD_WPP_BML:
                 case self::METHOD_WPP_DIRECT:
                 case self::METHOD_BILLING_AGREEMENT:
                 case self::METHOD_HOSTEDPRO:
@@ -1577,42 +1659,6 @@ class Config
         return $path;
     }
 
-    /**
-     * Check wheter specified country code is supported by build notation codes for specific countries
-     *
-     * @param string $code
-     * @return string|null
-     */
-    private function _matchBnCountryCode($code)
-    {
-        switch ($code) {
-            // GB == UK
-            case 'GB':
-                return 'UK';
-                // Australia, Austria, Belgium, Canada, China, France, Germany, Hong Kong, Italy
-            case 'AU':
-            case 'AT':
-            case 'BE':
-            case 'CA':
-            case 'CN':
-            case 'FR':
-            case 'DE':
-            case 'HK':
-            case 'IT':
-                // Japan, Mexico, Netherlands, Poland, Singapore, Spain, Switzerland, United Kingdom, United States
-            case 'JP':
-            case 'MX':
-            case 'NL':
-            case 'PL':
-            case 'SG':
-            case 'ES':
-            case 'CH':
-            case 'UK':
-            case 'US':
-                return $code;
-        }
-    }
-
     /**
      * Map PayPal Standard config fields
      *
@@ -1654,6 +1700,40 @@ class Config
         }
     }
 
+    /**
+     * Map PayPal Express Bill Me Later config fields
+     *
+     * @param string $fieldName
+     * @return string|null
+     */
+    protected function _mapBmlFieldset($fieldName)
+    {
+        switch ($fieldName)
+        {
+            case 'allow_ba_signup':
+                return "payment/" . self::METHOD_WPP_EXPRESS . "/{$fieldName}";
+            default:
+                return $this->_mapExpressFieldset($fieldName);
+        }
+    }
+
+    /**
+     * Map PayPal Express Bill Me Later config fields (Payflow Edition)
+     *
+     * @param string $fieldName
+     * @return string|null
+     */
+    protected function _mapBmlPayflowFieldset($fieldName)
+    {
+        switch ($fieldName)
+        {
+            case 'allow_ba_signup':
+                return "payment/" . self::METHOD_WPP_PE_EXPRESS . "/{$fieldName}";
+            default:
+                return $this->_mapExpressFieldset($fieldName);
+        }
+    }
+
     /**
      * Map PayPal Direct config fields
      *
@@ -1821,4 +1901,75 @@ class Config
         $websiteId = $this->_storeManager->getStore($this->_storeId)->getWebsiteId();
         return $this->_certFactory->create()->loadByWebsite($websiteId, false)->getCertPath();
     }
+
+    /**
+     * Get PublisherId from stored config
+     *
+     * @return mixed
+     */
+    public function getBmlPublisherId()
+    {
+        return $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_BML . '/publisher_id',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+    }
+
+    /**
+     * Get Display option from stored config
+     * @param string $section
+     *
+     * @return mixed
+     */
+    public function getBmlDisplay($section)
+    {
+        $display = $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_BML . '/' . $section . '_display',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+        $bmlActive = $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_BML . '/active',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+        $bmlUkActive = $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_PE_BML . '/active',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+        return (($bmlActive && $this->isMethodActive(self::METHOD_WPP_EXPRESS))
+            || ($bmlUkActive && $this->isMethodActive(self::METHOD_WPP_PE_EXPRESS))) ? $display : 0;
+    }
+
+    /**
+     * Get Position option from stored config
+     * @param string $section
+     *
+     * @return mixed
+     */
+    public function getBmlPosition($section)
+    {
+        return $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_BML . '/' . $section . '_position',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+    }
+
+    /**
+     * Get Size option from stored config
+     * @param string $section
+     *
+     * @return mixed
+     */
+    public function getBmlSize($section)
+    {
+        return $this->_scopeConfig->getValue(
+            'payment/' . self::METHOD_WPP_BML . '/' . $section . '_size',
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            $this->_storeId
+        );
+    }
 }
diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php
index 6a48cd19f66..e4d2ecfe65c 100644
--- a/app/code/Magento/Paypal/Model/Express.php
+++ b/app/code/Magento/Paypal/Model/Express.php
@@ -25,6 +25,7 @@ namespace Magento\Paypal\Model;
 
 use Magento\Paypal\Model\Express\Checkout as ExpressCheckout;
 use Magento\Paypal\Model\Api\Nvp;
+use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException;
 use Magento\Sales\Model\Order\Payment;
 use Magento\Sales\Model\Order\Payment\Transaction;
 use Magento\Sales\Model\Quote;
@@ -169,6 +170,16 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected $_cartFactory;
 
+    /**
+     * @var \Magento\Checkout\Model\Session
+     */
+    protected $_checkoutSession;
+
+    /**
+     * @var \Magento\Framework\Model\ExceptionFactory
+     */
+    protected $_exception;
+
     /**
      * @param \Magento\Framework\Event\ManagerInterface $eventManager
      * @param \Magento\Payment\Helper\Data $paymentData
@@ -178,6 +189,8 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Framework\UrlInterface $urlBuilder
      * @param \Magento\Paypal\Model\CartFactory $cartFactory
+     * @param \Magento\Checkout\Model\Session $checkoutSession
+     * @param \Magento\Framework\Model\ExceptionFactory $exception
      * @param array $data
      */
     public function __construct(
@@ -189,12 +202,16 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\UrlInterface $urlBuilder,
         \Magento\Paypal\Model\CartFactory $cartFactory,
+        \Magento\Checkout\Model\Session $checkoutSession,
+        \Magento\Framework\Model\ExceptionFactory $exception,
         array $data = array()
     ) {
         parent::__construct($eventManager, $paymentData, $scopeConfig, $logAdapterFactory, $data);
         $this->_storeManager = $storeManager;
         $this->_urlBuilder = $urlBuilder;
         $this->_cartFactory = $cartFactory;
+        $this->_checkoutSession = $checkoutSession;
+        $this->_exception = $exception;
 
         $proInstance = array_shift($data);
         if ($proInstance && $proInstance instanceof \Magento\Paypal\Model\Pro) {
@@ -203,6 +220,29 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
             $this->_pro = $proFactory->create();
         }
         $this->_pro->setMethod($this->_code);
+        $this->_setApiProcessableErrors();
+    }
+
+    /**
+     * Set processable error codes to API model
+     *
+     * @return \Magento\Paypal\Model\Api\Nvp
+     */
+    protected function _setApiProcessableErrors()
+    {
+        return $this->_pro->getApi()->setProcessableErrors(
+            [
+                ApiProcessableException::API_INTERNAL_ERROR,
+                ApiProcessableException::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE,
+                ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL,
+                ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE,
+                ApiProcessableException::API_TRANSACTION_EXPIRED,
+                ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED,
+                ApiProcessableException::API_COUNTRY_FILTER_DECLINE,
+                ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
+                ApiProcessableException::API_OTHER_FILTER_DECLINE
+            ]
+        );
     }
 
     /**
@@ -298,7 +338,12 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
      */
     public function order(\Magento\Framework\Object $payment, $amount)
     {
-        $this->_placeOrder($payment, $amount);
+        $paypalTransactionData = $this->_checkoutSession->getPaypalTransactionData();
+        if (!is_array($paypalTransactionData)) {
+            $this->_placeOrder($payment, $amount);
+        } else {
+            $this->_importToPayment($this->_pro->getApi()->setData($paypalTransactionData), $payment);
+        }
 
         $payment->setAdditionalInformation($this->_isOrderPaymentActionKey, true);
 
@@ -309,7 +354,7 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
         $order = $payment->getOrder();
         $orderTransactionId = $payment->getTransactionId();
 
-        $api = $this->_callDoAuthorize($amount, $payment, $payment->getTransactionId());
+        $api = $this->_callDoAuthorize($amount, $payment, $orderTransactionId);
 
         $state = \Magento\Sales\Model\Order::STATE_PROCESSING;
         $status = true;
@@ -427,7 +472,9 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
 
             if ($authorizationTransaction->getIsClosed() || $voided) {
                 if ($payment->getAdditionalInformation($this->_authorizationCountKey) > $maxAuthorizationNumber - 1) {
-                    throw new \Magento\Framework\Model\Exception(__('The maximum number of child authorizations is reached.'));
+                    $this->_exception->create(
+                        ['message' => __('The maximum number of child authorizations is reached.')]
+                    );
                 }
                 $api = $this->_callDoAuthorize($amount, $payment, $authorizationTransaction->getParentTxnId());
 
@@ -728,13 +775,19 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
      */
     protected function _callDoAuthorize($amount, $payment, $parentTransactionId)
     {
-        $api = $this->_pro->resetApi()->getApi()->setAmount(
-            $amount
-        )->setCurrencyCode(
-            $payment->getOrder()->getBaseCurrencyCode()
-        )->setTransactionId(
-            $parentTransactionId
-        )->callDoAuthorization();
+        $apiData = $this->_pro->getApi()->getData();
+        foreach ($apiData as $k => $v) {
+            if (is_object($v)) {
+                unset($apiData[$k]);
+            }
+        }
+        $this->_checkoutSession->setPaypalTransactionData($apiData);
+        $this->_pro->resetApi();
+        $api = $this->_setApiProcessableErrors()
+            ->setAmount($amount)
+            ->setCurrencyCode($payment->getOrder()->getBaseCurrencyCode())
+            ->setTransactionId($parentTransactionId)
+            ->callDoAuthorization();
 
         $payment->setAdditionalInformation(
             $this->_authorizationCountKey,
diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php
index e014d89c4d5..b3ca649ad73 100644
--- a/app/code/Magento/Paypal/Model/Express/Checkout.php
+++ b/app/code/Magento/Paypal/Model/Express/Checkout.php
@@ -51,6 +51,13 @@ class Checkout
     const PAYMENT_INFO_TRANSPORT_REDIRECT = 'paypal_express_checkout_redirect_required';
     const PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT = 'paypal_ec_create_ba';
 
+    /**
+     * Flag which says that was used PayPal Express Checkout button for checkout
+     * Uses additional_information as storage
+     * @var string
+     */
+    const PAYMENT_INFO_BUTTON = 'button';
+
     /**
      * @var \Magento\Sales\Model\Quote
      */
@@ -124,6 +131,13 @@ class Checkout
      */
     protected $_isBARequested = false;
 
+    /**
+     * Flag for Bill Me Later mode
+     *
+     * @var bool
+     */
+    protected $_isBml = false;
+
     /**
      * Customer ID
      *
@@ -326,7 +340,6 @@ class Checkout
         $this->_customerData = $customerData;
         $this->_taxData = $taxData;
         $this->_checkoutData = $checkoutData;
-        $this->_customerSession = $customerSession;
         $this->_configCacheType = $configCacheType;
         $this->_logger = $logger;
         $this->_localeResolver = $localeResolver;
@@ -347,6 +360,8 @@ class Checkout
         $this->_customerDetailsBuilder = $customerDetailsBuilder;
         $this->_encryptor = $encryptor;
         $this->_messageManager = $messageManager;
+        $this->_customerSession = isset($params['session'])
+            && $params['session'] instanceof \Magento\Customer\Model\Session ? $params['session'] : $customerSession;
 
         if (isset($params['config']) && $params['config'] instanceof PaypalConfig) {
             $this->_config = $params['config'];
@@ -423,6 +438,18 @@ class Checkout
         return $this;
     }
 
+    /**
+     * Set flag that forces to use BillMeLater
+     *
+     * @param bool $isBml
+     * @return $this
+     */
+    public function setIsBml($isBml)
+    {
+        $this->_isBml = $isBml;
+        return $this;
+    }
+
     /**
      * Setter for customer
      *
@@ -459,10 +486,11 @@ class Checkout
      *
      * @param string $returnUrl
      * @param string $cancelUrl
+     * @param bool|null $button
      * @return string
      * @throws \Magento\Framework\Model\Exception
      */
-    public function start($returnUrl, $cancelUrl)
+    public function start($returnUrl, $cancelUrl, $button = null)
     {
         $this->_quote->collectTotals();
 
@@ -478,12 +506,15 @@ class Checkout
         $this->_quote->reserveOrderId()->save();
         // prepare API
         $this->_getApi();
+        $solutionType = $this->_config->getMerchantCountry() == 'DE'
+            ? \Magento\Paypal\Model\Config::EC_SOLUTION_TYPE_MARK
+            : $this->_config->getConfigValue('solutionType');
         $this->_api->setAmount($this->_quote->getBaseGrandTotal())
             ->setCurrencyCode($this->_quote->getBaseCurrencyCode())
             ->setInvNum($this->_quote->getReservedOrderId())
             ->setReturnUrl($returnUrl)
             ->setCancelUrl($cancelUrl)
-            ->setSolutionType($this->_config->getConfigValue('solutionType'))
+            ->setSolutionType($solutionType)
             ->setPaymentAction($this->_config->getConfigValue('paymentAction'))
         ;
         if ($this->_giropayUrls) {
@@ -497,6 +528,10 @@ class Checkout
             );
         }
 
+        if ($this->_isBml) {
+            $this->_api->setFundingSource('BML');
+        }
+
         $this->_setBillingAgreementRequest();
 
         if ($this->_config->getConfigValue('requireBillingAddress') == PaypalConfig::REQUIRE_BILLING_ADDRESS_ALL) {
@@ -555,12 +590,33 @@ class Checkout
         $this->_api->callSetExpressCheckout();
 
         $token = $this->_api->getToken();
-        $this->_redirectUrl = $this->_config->getExpressCheckoutStartUrl($token);
+        $this->_redirectUrl = $button ? $this->_config->getExpressCheckoutStartUrl($token)
+            : $this->_config->getPayPalBasicStartUrl($token);
+
+        $payment = $this->_quote->getPayment();
+        $payment->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT);
+        // Set flag that we came from Express Checkout button
+        if (!empty($button)) {
+            $payment->setAdditionalInformation(self::PAYMENT_INFO_BUTTON, 1);
+        } elseif ($payment->hasAdditionalInformation(self::PAYMENT_INFO_BUTTON)) {
+            $payment->unsAdditionalInformation(self::PAYMENT_INFO_BUTTON);
+        }
+        $payment->save();
 
-        $this->_quote->getPayment()->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT)->save();
         return $token;
     }
 
+    /**
+     * Check whether system can skip order review page before placing order
+     *
+     * @return bool
+     */
+    public function canSkipOrderReviewStep()
+    {
+        $isOnepageCheckout = !$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
+        return $this->_config->isOrderReviewStepDisabled() && $isOnepageCheckout;
+    }
+
     /**
      * Update quote when returned from PayPal
      * rewrite billing address by paypal
@@ -579,25 +635,20 @@ class Checkout
 
         $this->_ignoreAddressValidation();
 
-        // import billing address
-        $billingAddress = $quote->getBillingAddress();
-        $exportedBillingAddress = $this->_api->getExportedBillingAddress();
-        $quote->setCustomerEmail($billingAddress->getEmail());
-        $quote->setCustomerPrefix($billingAddress->getPrefix());
-        $quote->setCustomerFirstname($billingAddress->getFirstname());
-        $quote->setCustomerMiddlename($billingAddress->getMiddlename());
-        $quote->setCustomerLastname($billingAddress->getLastname());
-        $quote->setCustomerSuffix($billingAddress->getSuffix());
-        $quote->setCustomerNote($exportedBillingAddress->getData('note'));
-        $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
-
         // import shipping address
         $exportedShippingAddress = $this->_api->getExportedShippingAddress();
         if (!$quote->getIsVirtual()) {
             $shippingAddress = $quote->getShippingAddress();
             if ($shippingAddress) {
-                if ($exportedShippingAddress) {
+                if ($exportedShippingAddress
+                    && $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1
+                ) {
                     $this->_setExportedAddressData($shippingAddress, $exportedShippingAddress);
+                    // PayPal doesn't provide detailed shipping info: prefix, middlename, lastname, suffix
+                    $shippingAddress->setPrefix(null);
+                    $shippingAddress->setMiddlename(null);
+                    $shippingAddress->setLastname(null);
+                    $shippingAddress->setSuffix(null);
                     $shippingAddress->setCollectShippingRates(true);
                     $shippingAddress->setSameAsBilling(0);
                 }
@@ -618,6 +669,32 @@ class Checkout
             }
         }
 
+        // import billing address
+        $portBillingFromShipping = $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1
+            && $this->_config->getConfigValue(
+                'requireBillingAddress'
+            ) != \Magento\Paypal\Model\Config::REQUIRE_BILLING_ADDRESS_ALL
+            && !$quote->isVirtual();
+        if ($portBillingFromShipping) {
+            $billingAddress = clone $shippingAddress;
+            $billingAddress->unsAddressId()->unsAddressType();
+            $data = $billingAddress->getData();
+            $data['save_in_address_book'] = 0;
+            $quote->getBillingAddress()->addData($data);
+            $quote->getShippingAddress()->setSameAsBilling(1);
+        } else {
+            $billingAddress = $quote->getBillingAddress();
+        }
+        $exportedBillingAddress = $this->_api->getExportedBillingAddress();
+        $quote->setCustomerEmail($billingAddress->getEmail());
+        $quote->setCustomerPrefix($billingAddress->getPrefix());
+        $quote->setCustomerFirstname($billingAddress->getFirstname());
+        $quote->setCustomerMiddlename($billingAddress->getMiddlename());
+        $quote->setCustomerLastname($billingAddress->getLastname());
+        $quote->setCustomerSuffix($billingAddress->getSuffix());
+        $quote->setCustomerNote($exportedBillingAddress->getData('note'));
+        $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
+
         // import payment info
         $payment = $quote->getPayment();
         $payment->setMethod($this->_methodType);
@@ -703,43 +780,11 @@ class Checkout
             if ($methodCode != $shippingAddress->getShippingMethod()) {
                 $this->_ignoreAddressValidation();
                 $shippingAddress->setShippingMethod($methodCode)->setCollectShippingRates(true);
-                $this->_quote->collectTotals();
+                $this->_quote->collectTotals()->save();
             }
         }
     }
 
-    /**
-     * Update order data
-     *
-     * @param array $data
-     * @return void
-     */
-    public function updateOrder($data)
-    {
-        /** @var $checkout \Magento\Checkout\Model\Type\Onepage */
-        $checkout = $this->_checkoutOnepageFactory->create();
-
-        $this->_quote->setTotalsCollectedFlag(true);
-        $checkout->setQuote($this->_quote);
-        if (isset($data['billing'])) {
-            if (isset($data['customer-email'])) {
-                $data['billing']['email'] = $data['customer-email'];
-            }
-            $checkout->saveBilling($data['billing'], 0);
-        }
-        if (!$this->_quote->getIsVirtual() && isset($data['shipping'])) {
-            $checkout->saveShipping($data['shipping'], 0);
-        }
-
-        if (isset($data['shipping_method'])) {
-            $this->updateShippingMethod($data['shipping_method']);
-        }
-        $this->_quote->setTotalsCollectedFlag(false);
-        $this->_quote->collectTotals();
-        $this->_quote->setDataChanges(true);
-        $this->_quote->save();
-    }
-
     /**
      * Place the order when customer returned from PayPal until this moment all quote data must be valid.
      *
@@ -886,20 +931,31 @@ class Checkout
      */
     protected function _setExportedAddressData($address, $exportedAddress)
     {
-        foreach ($exportedAddress->getExportedKeys() as $key) {
-            $oldData = $address->getDataUsingMethod($key);
-            $isEmpty = null;
-            if (is_array($oldData)) {
-                foreach ($oldData as $val) {
-                    if (!empty($val)) {
-                        $isEmpty = false;
-                        break;
+        // Exported data is more priority if we came from Express Checkout button
+        $isButton  = (bool)$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
+        if (!$isButton) {
+            foreach ($exportedAddress->getExportedKeys() as $key) {
+                $oldData = $address->getDataUsingMethod($key);
+                $isEmpty = null;
+                if (is_array($oldData)) {
+                    foreach ($oldData as $val) {
+                        if (!empty($val)) {
+                            $isEmpty = false;
+                            break;
+                        }
+                        $isEmpty = true;
                     }
-                    $isEmpty = true;
+                }
+                if (empty($oldData) || $isEmpty === true) {
+                    $address->setDataUsingMethod($key, $exportedAddress->getData($key));
                 }
             }
-            if (empty($oldData) || $isEmpty === true) {
-                $address->setDataUsingMethod($key, $exportedAddress->getData($key));
+        } else {
+            foreach ($exportedAddress->getExportedKeys() as $key) {
+                $data = $exportedAddress->getData($key);
+                if (!empty($data)) {
+                    $address->setDataUsingMethod($key, $data);
+                }
             }
         }
     }
diff --git a/app/code/Magento/Paypal/Model/Observer.php b/app/code/Magento/Paypal/Model/Observer.php
index bb4e0f09588..c2d6515ab78 100644
--- a/app/code/Magento/Paypal/Model/Observer.php
+++ b/app/code/Magento/Paypal/Model/Observer.php
@@ -81,6 +81,16 @@ class Observer
      */
     protected $_checkoutSession;
 
+    /**
+     * @var \Magento\Paypal\Helper\Shortcut\Factory
+     */
+    protected $_shortcutFactory;
+
+    /**
+     * Shortcut template path
+     */
+    const SHORTCUT_TEMPLATE = 'express/shortcut.phtml';
+
     /**
      * @param \Magento\Core\Helper\Data $coreData
      * @param \Magento\Paypal\Helper\Hss $paypalHss
@@ -91,6 +101,7 @@ class Observer
      * @param \Magento\Framework\AuthorizationInterface $authorization
      * @param \Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory
      * @param \Magento\Checkout\Model\Session $checkoutSession
+     * @param \Magento\Paypal\Helper\Shortcut\Factory $shortcutFactory
      */
     public function __construct(
         \Magento\Core\Helper\Data $coreData,
@@ -101,7 +112,8 @@ class Observer
         \Magento\Framework\App\ViewInterface $view,
         \Magento\Framework\AuthorizationInterface $authorization,
         \Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory,
-        \Magento\Checkout\Model\Session $checkoutSession
+        \Magento\Checkout\Model\Session $checkoutSession,
+        \Magento\Paypal\Helper\Shortcut\Factory $shortcutFactory
     ) {
         $this->_coreData = $coreData;
         $this->_paypalHss = $paypalHss;
@@ -112,6 +124,7 @@ class Observer
         $this->_authorization = $authorization;
         $this->_agreementFactory = $agreementFactory;
         $this->_checkoutSession = $checkoutSession;
+        $this->_shortcutFactory = $shortcutFactory;
     }
 
     /**
@@ -255,33 +268,34 @@ class Observer
     {
         /** @var \Magento\Catalog\Block\ShortcutButtons $shortcutButtons */
         $shortcutButtons = $observer->getEvent()->getContainer();
-        // PayPal Express Checkout
-        $shortcut = $shortcutButtons->getLayout()->createBlock(
+        $blocks = [
             'Magento\Paypal\Block\Express\Shortcut',
-            '',
-            array('checkoutSession' => $observer->getEvent()->getCheckoutSession())
-        );
-        $shortcut->setIsInCatalogProduct(
-            $observer->getEvent()->getIsCatalogProduct()
-        )->setShowOrPosition(
-            $observer->getEvent()->getOrPosition()
-        )->setTemplate(
-            'express/shortcut.phtml'
-        );
-        $shortcutButtons->addShortcut($shortcut);
-        // PayPal Express Checkout Payflow Edition
-        $shortcut = $shortcutButtons->getLayout()->createBlock(
             'Magento\Paypal\Block\PayflowExpress\Shortcut',
-            '',
-            array('checkoutSession' => $observer->getEvent()->getCheckoutSession())
-        );
-        $shortcut->setIsInCatalogProduct(
-            $observer->getEvent()->getIsCatalogProduct()
-        )->setShowOrPosition(
-            $observer->getEvent()->getOrPosition()
-        )->setTemplate(
-            'express/shortcut.phtml'
-        );
-        $shortcutButtons->addShortcut($shortcut);
+            'Magento\Paypal\Block\Bml\Shortcut',
+            'Magento\Paypal\Block\Payflow\Bml\Shortcut'
+        ];
+        foreach ($blocks as $blockInstanceName) {
+            $params = [
+                'shortcutValidator' => $this->_shortcutFactory->create($observer->getEvent()->getCheckoutSession())
+            ];
+            if (!in_array('Bml', explode('/', $blockInstanceName))) {
+                $params['checkoutSession'] = $observer->getEvent()->getCheckoutSession();
+            }
+
+            // we believe it's \Magento\Framework\View\Element\Template
+            $shortcut = $shortcutButtons->getLayout()->createBlock(
+                $blockInstanceName,
+                '',
+                $params
+            );
+            $shortcut->setIsInCatalogProduct(
+                $observer->getEvent()->getIsCatalogProduct()
+            )->setShowOrPosition(
+                $observer->getEvent()->getOrPosition()
+            )->setTemplate(
+                self::SHORTCUT_TEMPLATE
+            );
+            $shortcutButtons->addShortcut($shortcut);
+        }
     }
 }
diff --git a/app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php b/app/code/Magento/Paypal/Model/Payflow/Bml.php
similarity index 63%
rename from app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php
rename to app/code/Magento/Paypal/Model/Payflow/Bml.php
index adbf3c76148..e7e3f706a6c 100644
--- a/app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php
+++ b/app/code/Magento/Paypal/Model/Payflow/Bml.php
@@ -21,42 +21,32 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+ 
+namespace Magento\Paypal\Model\Payflow;
 
-/**
- * Paypal expess checkout shortcut link
- */
-namespace Magento\Paypal\Block\PayflowExpress;
+use Magento\Paypal\Model;
 
-class Shortcut extends \Magento\Paypal\Block\Express\Shortcut
+class Bml extends Model\Express
 {
     /**
      * Payment method code
-     *
      * @var string
      */
-    protected $_paymentMethodCode = \Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS;
+    protected $_code  = Model\Config::METHOD_WPP_PE_BML;
 
     /**
-     * Start express action
-     *
-     * @var string
-     */
-    protected $_startAction = 'paypal/payflowexpress/start';
-
-    /**
-     * Express checkout model factory name
-     *
+     * Checkout payment form
      * @var string
      */
-    protected $_checkoutType = 'Magento\Paypal\Model\PayflowExpress\Checkout';
+    protected $_formBlockType = 'Magento\Paypal\Block\Payflow\Bml\Form';
 
     /**
-     * Get shortcut alias
+     * Checkout redirect URL getter for onepage checkout
      *
      * @return string
      */
-    public function getAlias()
+    public function getCheckoutRedirectUrl()
     {
-        return 'product.info.addtocart.payflow';
+        return $this->_urlBuilder->getUrl('paypal/payflowbml/start');
     }
 }
diff --git a/app/code/Magento/Paypal/Model/PayflowExpress.php b/app/code/Magento/Paypal/Model/PayflowExpress.php
index 50d0c2081fb..b98753af068 100644
--- a/app/code/Magento/Paypal/Model/PayflowExpress.php
+++ b/app/code/Magento/Paypal/Model/PayflowExpress.php
@@ -59,6 +59,8 @@ class PayflowExpress extends \Magento\Paypal\Model\Express
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Framework\UrlInterface $urlBuilder
      * @param CartFactory $cartFactory
+     * @param \Magento\Checkout\Model\Session $checkoutSession
+     * @param \Magento\Framework\Model\ExceptionFactory $exception
      * @param InfoFactory $paypalInfoFactory
      * @param array $data
      */
@@ -71,6 +73,8 @@ class PayflowExpress extends \Magento\Paypal\Model\Express
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Framework\UrlInterface $urlBuilder,
         CartFactory $cartFactory,
+        \Magento\Checkout\Model\Session $checkoutSession,
+        \Magento\Framework\Model\ExceptionFactory $exception,
         InfoFactory $paypalInfoFactory,
         array $data = array()
     ) {
@@ -83,6 +87,8 @@ class PayflowExpress extends \Magento\Paypal\Model\Express
             $storeManager,
             $urlBuilder,
             $cartFactory,
+            $checkoutSession,
+            $exception,
             $data
         );
         $this->_paypalInfoFactory = $paypalInfoFactory;
diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php
index d63d3ffa155..989980c6f45 100644
--- a/app/code/Magento/Paypal/Model/Payflowlink.php
+++ b/app/code/Magento/Paypal/Model/Payflowlink.php
@@ -561,6 +561,8 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro
         /** @var \Magento\Paypal\Model\Payflow\Request $request */
         $request = $this->_requestFactory->create();
         $cscEditable = $this->getConfigData('csc_editable');
+        /** @var \Magento\Paypal\Model\Config $config */
+        $config = $this->_configFactory->create();
         $request->setUser(
             $this->getConfigData('user', $this->_getStoreId())
         )->setVendor(
@@ -573,7 +575,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro
             $this->getConfigData('verbosity', $this->_getStoreId())
         )->setData(
             'BNCODE',
-            $this->getConfigData('bncode')
+            $config->getBuildNotationCode()
         )->setTender(
             self::TENDER_CC
         )->setCancelurl(
diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php
index dd9934815ae..2a08c4e4c30 100644
--- a/app/code/Magento/Paypal/Model/Payflowpro.php
+++ b/app/code/Magento/Paypal/Model/Payflowpro.php
@@ -683,6 +683,8 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
     protected function _buildBasicRequest(\Magento\Framework\Object $payment)
     {
         $request = new \Magento\Framework\Object();
+        /** @var \Magento\Paypal\Model\Config $config */
+        $config = $this->_configFactory->create();
         $request->setUser(
             $this->getConfigData('user')
         )->setVendor(
@@ -693,6 +695,9 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc
             $this->getConfigData('pwd')
         )->setVerbosity(
             $this->getConfigData('verbosity')
+        )->setData(
+            'BNCODE',
+            $config->getBuildNotationCode()
         )->setTender(
             self::TENDER_CC
         )->setRequestId(
diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php b/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php
new file mode 100644
index 00000000000..94c008f53dc
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model\System\Config\Source;
+
+class BmlPosition
+{
+    /**
+     * Bml positions source getter for Home Page
+     *
+     * @return array
+     */
+    public function getBmlPositionsHP()
+    {
+        return [
+            '0' => __('Header (center)'),
+            '1' => __('Sidebar (right)')
+        ];
+    }
+
+    /**
+     * Bml positions source getter for Catalog Category Page
+     *
+     * @return array
+     */
+    public function getBmlPositionsCCP()
+    {
+        return [
+            '0' => __('Header (center)'),
+            '1' => __('Sidebar (right)')
+        ];
+    }
+
+    /**
+     * Bml positions source getter for Catalog Product Page
+     *
+     * @return array
+     */
+    public function getBmlPositionsCPP()
+    {
+        return [
+            '0' => __('Header (center)'),
+            '1' => __('Near Bill Me Later checkout button')
+        ];
+    }
+
+    /**
+     * Bml positions source getter for Checkout Cart Page
+     *
+     * @return array
+     */
+    public function getBmlPositionsCheckout()
+    {
+        return [
+            '0' => __('Header (center)'),
+            '1' => __('Near Bill Me Later checkout button')
+        ];
+    }
+}
diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php b/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php
new file mode 100644
index 00000000000..a1c846c7812
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model\System\Config\Source;
+
+class BmlSize
+{
+    /**
+     * Options getter for Home Page and position Header
+     *
+     * @return array
+     */
+    public function getBmlSizeHPH()
+    {
+        return [
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '300x50' => '300 x 50',
+            '468x60' => '468 x 60',
+            '728x90' => '728 x 90',
+            '800x66' => '800 x 66'
+        ];
+    }
+
+    /**
+     * Options getter for Home Page and position Sidebar (right)
+     *
+     * @return array
+     */
+    public function getBmlSizeHPS()
+    {
+        return [
+            '120x90' => '120 x 90',
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '120x240' => '120 x 240',
+            '120x600' => '120 x 600',
+            '234x400' => '234 x 400',
+            '250x250' => '250 x 250'
+        ];
+    }
+
+    /**
+     * Options getter for Catalog Category Page and position Center
+     *
+     * @return array
+     */
+    public function getBmlSizeCCPC()
+    {
+        return [
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '300x50' => '300 x 50',
+            '468x60' => '468 x 60',
+            '728x90' => '728 x 90',
+            '800x66' => '800 x 66'
+        ];
+    }
+
+    /**
+     * Options getter for Catalog Category Page and position Sidebar (right)
+     *
+     * @return array
+     */
+    public function getBmlSizeCCPS()
+    {
+        return [
+            '120x90' => '120 x 90',
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '120x240' => '120 x 240',
+            '120x600' => '120 x 600',
+            '234x400' => '234 x 400',
+            '250x250' => '250 x 250'
+        ];
+    }
+
+    /**
+     * Options getter for Catalog Product Page and position Center
+     *
+     * @return array
+     */
+    public function getBmlSizeCPPC()
+    {
+        return [
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '300x50' => '300 x 50',
+            '468x60' => '468 x 60',
+            '728x90' => '728 x 90',
+            '800x66' => '800 x 66'
+        ];
+    }
+
+    /**
+     * Options getter for Catalog Product Page and position Near Bill Me Later checkout button
+     *
+     * @return array
+     */
+    public function getBmlSizeCPPN()
+    {
+        return [
+            '120x90' => '120 x 90',
+            '190x100' => '190 x 100',
+            '234x60' => '234 x 60',
+            '120x240' => '120 x 240',
+            '120x600' => '120 x 600',
+            '234x400' => '234 x 400',
+            '250x250' => '250 x 250'
+        ];
+    }
+
+    /**
+     * Options getter for Checkout Cart Page and position Center
+     *
+     * @return array
+     */
+    public function getBmlSizeCheckoutC()
+    {
+        return [
+            '234x60' => '234 x 60',
+            '300x50' => '300 x 50',
+            '468x60' => '468 x 60',
+            '728x90' => '728 x 90',
+            '800x66' => '800 x 66'
+        ];
+    }
+
+    /**
+     * Options getter for Checkout Cart Page and position Near Bill Me Later checkout button
+     *
+     * @return array
+     */
+    public function getBmlSizeCheckoutN()
+    {
+        return [
+            '234x60' => '234 x 60',
+            '300x50' => '300 x 50',
+            '468x60' => '468 x 60'
+        ];
+    }
+}
diff --git a/app/code/Magento/Paypal/etc/adminhtml/system.xml b/app/code/Magento/Paypal/etc/adminhtml/system.xml
index 82bf0a09bf3..6f826847aef 100644
--- a/app/code/Magento/Paypal/etc/adminhtml/system.xml
+++ b/app/code/Magento/Paypal/etc/adminhtml/system.xml
@@ -79,6 +79,109 @@
                         <frontend_class>paypal-enabler</frontend_class>
                         <attribute type="shared">1</attribute>
                     </field>
+                    <field id="enable_express_checkout_bml" sortOrder="21" extends="payment_all_paypal/express_checkout/express_checkout_required/enable_express_checkout_bml">
+                        <comment><![CDATA[Website Payments Pro lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                                        You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                                        <a href="https://www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                        </comment>
+                        <requires>
+                            <field id="enable_wpp"/>
+                        </requires>
+                    </field>
+                    <group id="wpp_advertise_bml" showInDefault="1" showInWebsite="1" sortOrder="22" translate="label comment">
+                        <label>Advertise Bill Me Later</label>
+                        <comment>
+                            <![CDATA[<a href="https://financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                                            <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                                            from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                                            Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                                            The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                                            or more. <a href="https://financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                        </comment>
+                        <field id="bml_publisher_id" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_publisher_id" />
+                        <field id="bml_wizard" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_wizard" />
+                        <group id="wpp_settings_bml_homepage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20" translate="label">
+                            <label>Home Page</label>
+                            <field id="bml_homepage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_display"/>
+                            <field id="wpp_bml_homepage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_position"/>
+                            <field id="wpp_bml_homepage_size1" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                <depends>
+                                    <field id="wpp_bml_homepage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="wpp_bml_homepage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_homepage/advanced_bml_homepage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                <depends>
+                                    <field id="wpp_bml_homepage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="wpp_settings_bml_categorypage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="30" translate="label">
+                            <label>Catalog Category Page</label>
+                            <field id="bml_categorypage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_display"/>
+                            <field id="wpp_bml_categorypage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_position"/>
+                            <field id="wpp_bml_categorypage_size1" type="select" showInDefault="1" showInWebsite="1" sortOrder="30" translate="label">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="wpp_bml_categorypage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="wpp_bml_categorypage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_categorypage/advanced_bml_categorypage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                <depends>
+                                    <field id="wpp_bml_categorypage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="wpp_settings_bml_productpage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="40" translate="label">
+                            <label>Catalog Product Page</label>
+                            <field id="bml_productpage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_display" />
+                            <field id="wpp_bml_productpage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_position" />
+                            <field id="wpp_bml_productpage_size1" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" translate="label">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="wpp_bml_productpage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="wpp_bml_productpage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_productpage/advanced_bml_productpage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                <depends>
+                                    <field id="wpp_bml_productpage_position">1</field>
+                                </depends>
+                            </field>
+
+                        </group>
+                        <group id="wpp_settings_bml_checkout" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="50" translate="label">
+                            <label>Checkout Cart Page</label>
+                            <field id="bml_checkout_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_display"/>
+                            <field id="wpp_bml_checkout_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_position"/>
+                            <field id="wppw_bml_checkout_size1" type="select" showInDefault="1" showInWebsite="1" sortOrder="30" translate="label">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="wpp_bml_checkout_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="wpp_bml_checkout_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_checkout/advanced_bml_checkout_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="wpp_bml_checkout_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                    </group>
                 </group>
                 <group id="wpp_settings" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
                     <label>Basic Settings - PayPal Website Payments Pro</label>
@@ -250,6 +353,7 @@
                         <field id="solution_type" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/solution_type"/>
                         <field id="require_billing_address" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/require_billing_address"/>
                         <field id="allow_ba_signup" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/allow_ba_signup"/>
+                        <field id="skip_order_review_step" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/skip_order_review_step"/>
                     </group>
                 </group>
             </group>
@@ -639,6 +743,111 @@
                             <field id="enable_payflow_link"/>
                         </requires>
                     </field>
+
+                    <field id="enable_express_checkout_bml"  extends="payment_all_paypal/express_checkout/express_checkout_required/enable_express_checkout_bml" sortOrder="41">
+                        <comment><![CDATA[Payflow Link lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                        You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                        <a href="https:/www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                        </comment>
+                        <config_path>payment/paypal_express_bml/active</config_path>
+                        <requires>
+                            <field id="enable_express_checkout"/>
+                        </requires>
+                    </field>
+                    <group id="payflow_link_advertise_bml"  translate="label comment" showInDefault="1" showInWebsite="1" sortOrder="42">
+                        <label>Advertise Bill Me Later</label>
+                        <comment>
+                            <![CDATA[<a href="https:/financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                        <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                        from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                        Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                        The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                        or more. <a href="https:/financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                        </comment>
+                        <field id="bml_publisher_id" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_publisher_id" />
+                        <field id="bml_wizard" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_wizard" />
+                        <group id="payflow_link_settings_bml_homepage"  translate="label" showInWebsite="1" sortOrder="20" showInDefault="1" showInStore="1">
+                            <label>Home Page</label>
+                            <field id="bml_homepage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_display"/>
+                            <field id="payflow_link_bml_homepage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_position"/>
+                            <field id="payflow_link_bml_homepage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="payflow_link_bml_homepage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="payflow_link_bml_homepage_size2" extends="payment_all_paypal/payflow_link/payflow_link_required/payflow_link_advertise_bml/payflow_link_settings_bml_homepage/payflow_link_bml_homepage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                <depends>
+                                    <field id="payflow_link_bml_homepage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="payflow_link_settings_bml_categorypage"  translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
+                            <label>Catalog Category Page</label>
+                            <field id="bml_categorypage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_display"/>
+                            <field id="payflow_link_bml_categorypage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_position" />
+                            <field id="payflow_link_bml_categorypage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="40">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="payflow_link_bml_categorypage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="payflow_link_bml_categorypage_size2" extends="payment_all_paypal/payflow_link/payflow_link_required/payflow_link_advertise_bml/payflow_link_settings_bml_categorypage/payflow_link_bml_categorypage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                <depends>
+                                    <field id="payflow_link_bml_categorypage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="payflow_link_settings_bml_productpage"  translate="label" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="50">
+                            <label>Catalog Product Page</label>
+                            <field id="bml_productpage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_display" />
+                            <field id="payflow_link_bml_productpage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_position" />
+                            <field id="payflow_link_bml_productpage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="payflow_link_bml_productpage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="payflow_link_bml_productpage_size2" extends="payment_all_paypal/payflow_link/payflow_link_required/payflow_link_advertise_bml/payflow_link_settings_bml_productpage/payflow_link_bml_productpage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                <depends>
+                                    <field id="payflow_link_bml_productpage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="payflow_link_settings_bml_checkout"  translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="60">
+                            <label>Checkout Cart Page</label>
+                            <field id="bml_checkout_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_display" />
+                            <field id="payflow_link_bml_checkout_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_position" />
+                            <field id="payflow_link_bml_checkout_size1" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="payflow_link_bml_checkout_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="payflow_link_bml_checkout_size2" extends="payment_all_paypal/payflow_link/payflow_link_required/payflow_link_advertise_bml/payflow_link_settings_bml_checkout/payflow_link_bml_checkout_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="payflow_link_bml_checkout_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                    </group>
                 </group>
                 <group id="settings_payflow_link" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
                     <label>Basic Settings - PayPal Payflow Link</label>
@@ -865,6 +1074,153 @@
                         </requires>
                         <frontend_class>paypal-enabler paypal-ec-enabler</frontend_class>
                     </field>
+
+                    <field id="enable_express_checkout_bml" translate="label comment" type="select" sortOrder="21" showInDefault="1" showInWebsite="1">
+                        <label>Enable Bill Me Later</label>
+                        <comment><![CDATA[PayPal Express Checkout lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                        You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                        <a href="https:/www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                        </comment>
+                        <config_path>payment/paypal_express_bml/active</config_path>
+                        <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                        <attribute type="shared">1</attribute>
+                        <requires>
+                            <field id="enable_express_checkout"/>
+                        </requires>
+                        <frontend_class>paypal-bml</frontend_class>
+                    </field>
+                    <group id="advertise_bml" translate="label comment" showInDefault="1" showInWebsite="1" sortOrder="30">
+                        <label>Advertise Bill Me Later</label>
+                        <comment>
+                            <![CDATA[<a href="https:/financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                        <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                        from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                        Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                        The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                        or more. <a href="https:/financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                        </comment>
+                        <field id="bml_publisher_id" translate="label comment tooltip" showInDefault="1" showInWebsite="1" sortOrder="10">
+                            <label>Publisher ID</label>
+                            <comment><![CDATA[Required to display a banner]]></comment>
+                            <config_path>payment/paypal_express_bml/publisher_id</config_path>
+                            <attribute type="shared">1</attribute>
+                        </field>
+                        <field id="bml_wizard" translate="button_label" sortOrder="15" showInDefault="1" showInWebsite="1">
+                            <label></label>
+                            <button_label>Get Publisher ID from PayPal</button_label>
+                            <button_url><![CDATA[https:/financing.paypal.com/ppfinportal/cart/index?dcp=4eff8563b9cc505e0b9afaff3256705081553c79]]></button_url>
+                            <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\BmlApiWizard</frontend_model>
+                        </field>
+                        <group id="settings_bml_homepage" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
+                            <label>Home Page</label>
+                            <field id="bml_homepage_display" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="10">
+                                <label>Display</label>
+                                <config_path>payment/paypal_express_bml/homepage_display</config_path>
+                                <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_homepage_position" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="20">
+                                <label>Position</label>
+                                <config_path>payment/paypal_express_bml/homepage_position</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlPosition::getBmlPositionsHP</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_homepage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="bml_homepage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="bml_homepage_size2" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                <depends>
+                                    <field id="bml_homepage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="settings_bml_categorypage" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
+                            <label>Catalog Category Page</label>
+                            <field id="bml_categorypage_display" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="10">
+                                <label>Display</label>
+                                <config_path>payment/paypal_express_bml/categorypage_display</config_path>
+                                <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_categorypage_position" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="20">
+                                <label>Position</label>
+                                <config_path>payment/paypal_express_bml/categorypage_position</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlPosition::getBmlPositionsCCP</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_categorypage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends><field id="bml_categorypage_position">0</field></depends>
+                            </field>
+                            <field id="bml_categorypage_size2" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                <depends><field id="bml_categorypage_position">1</field></depends>
+                            </field>
+                        </group>
+                        <group id="settings_bml_productpage" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="40">
+                            <label>Catalog Product Page</label>
+                            <field id="bml_productpage_display" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="10">
+                                <label>Display</label>
+                                <config_path>payment/paypal_express_bml/productpage_display</config_path>
+                                <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_productpage_position" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="20">
+                                <label>Position</label>
+                                <config_path>payment/paypal_express_bml/productpage_position</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlPosition::getBmlPositionsCPP</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_productpage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends><field id="bml_productpage_position">0</field></depends>
+                            </field>
+                            <field id="bml_productpage_size2" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                <depends><field id="bml_productpage_position">1</field></depends>
+                            </field>
+                        </group>
+                        <group id="settings_bml_checkout" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="50">
+                            <label>Checkout Cart Page</label>
+                            <field id="bml_checkout_display" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="10">
+                                <label>Display</label>
+                                <config_path>payment/paypal_express_bml/checkout_display</config_path>
+                                <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_checkout_position" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="20">
+                                <label>Position</label>
+                                <config_path>payment/paypal_express_bml/checkout_position</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlPosition::getBmlPositionsCheckout</source_model>
+                                <attribute type="shared">1</attribute>
+                            </field>
+                            <field id="bml_checkout_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends><field id="bml_checkout_position">0</field></depends>
+                            </field>
+                            <field id="bml_checkout_size2" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends><field id="bml_checkout_position">1</field></depends>
+                            </field>
+                        </group>
+                    </group>
                 </group>
                 <group id="settings_ec" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
                     <label>Basic Settings - PayPal Express Checkout</label>
@@ -1004,6 +1360,12 @@
                             <source_model>Magento\Paypal\Model\Config::getExpressCheckoutBASignupOptions</source_model>
                             <attribute type="shared">1</attribute>
                         </field>
+                        <field id="skip_order_review_step" translate="label" type="select" sortOrder="95" showInDefault="1" showInWebsite="1">
+                            <label>Skip Order Review Step</label>
+                            <config_path>payment/paypal_express/skip_order_review_step</config_path>
+                            <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                            <attribute type="shared">1</attribute>
+                        </field>
                         <group id="express_checkout_billing_agreement" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="100">
                             <label>PayPal Billing Agreement Settings</label>
                             <field id="active" translate="label comment" type="select" sortOrder="10" showInDefault="1" showInWebsite="1">
@@ -1230,6 +1592,110 @@
                         </requires>
                         <frontend_class>paypal-enabler paypal-ec-separate</frontend_class>
                     </field>
+
+                    <field id="enable_express_checkout_bml"  extends="payment_all_paypal/express_checkout/express_checkout_required/enable_express_checkout_bml" sortOrder="21">
+                        <comment><![CDATA[Payments Pro Hosted Solution lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                        You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                        <a href="https:/www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                        </comment>
+                        <requires>
+                            <field id="pphs_enable"/>
+                        </requires>
+                    </field>
+                    <group id="pphs_advertise_bml"  translate="label comment" showInDefault="1" showInWebsite="1" sortOrder="22">
+                        <label>Advertise Bill Me Later</label>
+                        <comment>
+                            <![CDATA[<a href="https:/financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                            <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                            from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                            Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                            The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                            or more. <a href="https:/financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                        </comment>
+                        <field id="bml_publisher_id" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_publisher_id" />
+                        <field id="bml_wizard" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_wizard" />
+                        <group id="pphs_settings_bml_homepage"  translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
+                            <label>Home Page</label>
+                            <field id="bml_homepage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_display"/>
+                            <field id="pphs_bml_homepage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_position"/>
+                            <field id="pphs_bml_homepage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="pphs_bml_homepage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="pphs_bml_homepage_size2" extends="payment_all_paypal/payments_pro_hosted_solution/pphs_required_settings/pphs_advertise_bml/pphs_settings_bml_homepage/pphs_bml_homepage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                <depends>
+                                    <field id="pphs_bml_homepage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="pphs_settings_bml_categorypage"  translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="30">
+                            <label>Catalog Category Page</label>
+                            <field id="bml_categorypage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_display"/>
+                            <field id="pphs_bml_categorypage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_position" />
+                            <field id="pphs_bml_categorypage_size1" translate="label" showInDefault="1" showInWebsite="1" sortOrder="30" type="select">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="pphs_bml_categorypage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="pphs_bml_categorypage_size2" extends="payment_all_paypal/payments_pro_hosted_solution/pphs_required_settings/pphs_advertise_bml/pphs_settings_bml_categorypage/pphs_bml_categorypage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                <depends>
+                                    <field id="pphs_bml_categorypage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="pphs_settings_bml_productpage"  translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="40">
+                            <label>Catalog Product Page</label>
+                            <field id="bml_productpage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_display" />
+                            <field id="pphs_bml_productpage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_position" />
+                            <field id="pphs_bml_productpage_size1" translate="label" type="select" showInWebsite="1" showInDefault="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="pphs_bml_productpage_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="pphs_bml_productpage_size2" extends="payment_all_paypal/payments_pro_hosted_solution/pphs_required_settings/pphs_advertise_bml/pphs_settings_bml_productpage/pphs_bml_productpage_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                <depends>
+                                    <field id="pphs_bml_productpage_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                        <group id="pphs_settings_bml_checkout"  translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="50">
+                            <label>Checkout Cart Page</label>
+                            <field id="bml_checkout_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_display" />
+                            <field id="pphs_bml_checkout_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_position" />
+                            <field id="pphs_bml_checkout_size1" translate="label" type="select" showInWebsite="1" showInDefault="1" sortOrder="30">
+                                <label>Size</label>
+                                <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="pphs_bml_checkout_position">0</field>
+                                </depends>
+                            </field>
+                            <field id="pphs_bml_checkout_size2" extends="payment_all_paypal/payments_pro_hosted_solution/pphs_required_settings/pphs_advertise_bml/pphs_settings_bml_checkout/pphs_bml_checkout_size1">
+                                <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                <attribute type="shared">1</attribute>
+                                <depends>
+                                    <field id="pphs_bml_checkout_position">1</field>
+                                </depends>
+                            </field>
+                        </group>
+                    </group>
                 </group>
                 <group id="pphs_settings" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
                     <label>Basic Settings - PayPal Payments Pro Hosted Solution</label>
@@ -1394,7 +1860,7 @@
                                 <attribute type="shared">1</attribute>
                             </field>
                         </group>
-                        <field id="enable_payflow_advanced" translate="label comment" type="select" sortOrder="30" showInDefault="1" showInWebsite="1">
+                        <field id="enable_payflow_advanced" translate="label comment" type="select" sortOrder="41" showInDefault="1" showInWebsite="1">
                             <label>Enable this Solution</label>
                             <config_path>payment/payflow_advanced/active</config_path>
                             <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
@@ -1410,6 +1876,110 @@
                                 <field id="enable_payflow_advanced"/>
                             </requires>
                         </field>
+                        <field id="enable_express_checkout_bml" sortOrder="42" extends="payment_all_paypal/express_checkout/express_checkout_required/enable_express_checkout_bml">
+                            <comment><![CDATA[PayPal Payments Advanced lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                                        You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                                        <a href="https://www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                            </comment>
+                            <requires>
+                                <field id="enable_payflow_advanced"/>
+                            </requires>
+                        </field>
+
+                        <group id="advanced_advertise_bml" showInDefault="1" showInWebsite="1" sortOrder="43" translate="label comment">
+                            <label>Advertise Bill Me Later</label>
+                            <comment>
+                                <![CDATA[<a href="https://financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                                            <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                                            from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                                            Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                                            The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                                            or more. <a href="https://financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                            </comment>
+                            <field id="bml_publisher_id" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_publisher_id" />
+                            <field id="bml_wizard" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_wizard" />
+                            <group id="advanced_settings_bml_homepage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20" translate="label">
+                                <label>Home Page</label>
+                                <field id="bml_homepage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_display"/>
+                                <field id="advanced_bml_homepage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_position"/>
+                                <field id="advanced_bml_homepage_size1" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                    <depends>
+                                        <field id="advanced_bml_homepage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="advanced_bml_homepage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_homepage/advanced_bml_homepage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                    <depends>
+                                        <field id="advanced_bml_homepage_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                            <group id="advanced_settings_bml_categorypage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="30" translate="label">
+                                <label>Catalog Category Page</label>
+                                <field id="bml_categorypage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_display"/>
+                                <field id="advanced_bml_categorypage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_position"/>
+                                <field id="advanced_bml_categorypage_size1" type="select" showInDefault="1" showInWebsite="1" sortOrder="30" translate="label">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="advanced_bml_categorypage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="advanced_bml_categorypage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_categorypage/advanced_bml_categorypage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                    <depends>
+                                        <field id="advanced_bml_categorypage_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                            <group id="advanced_settings_bml_productpage" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="40" translate="label">
+                                <label>Catalog Product Page</label>
+                                <field id="bml_productpage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_display" />
+                                <field id="advanced_bml_productpage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_position" />
+                                <field id="advanced_bml_productpage_size1" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" translate="label">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="advanced_bml_productpage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="advanced_bml_productpage_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_productpage/advanced_bml_productpage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                    <depends>
+                                        <field id="advanced_bml_productpage_position">1</field>
+                                    </depends>
+                                </field>
+
+                            </group>
+                            <group id="advanced_settings_bml_checkout" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="50" translate="label">
+                                <label>Checkout Cart Page</label>
+                                <field id="bml_checkout_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_display"/>
+                                <field id="advanced_bml_checkout_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_position"/>
+                                <field id="advanced_bml_checkout_size1" type="select" showInDefault="1" showInWebsite="1" sortOrder="30" translate="label">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="advanced_bml_checkout_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="advanced_bml_checkout_size2" extends="payment_us/paypal_group_all_in_one/payflow_advanced/required_settings/advanced_advertise_bml/advanced_settings_bml_checkout/advanced_bml_checkout_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="advanced_bml_checkout_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                        </group>
                     </group>
                     <group id="settings_payments_advanced" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
                         <label>Basic Settings - PayPal Payments Advanced</label>
@@ -1572,6 +2142,116 @@
                                 <field id="enable_paypal_payflow"/>
                             </requires>
                         </field>
+
+
+                        <field id="enable_express_checkout_bml_payflow" translate="label" type="select" sortOrder="21" showInWebsite="1" showInDefault="1">
+                            <label>Enable Bill Me Later</label>
+                            <comment><![CDATA[PayPal Express Checkout Payflow Edition lets you give customers access to financing through Bill Me Later&#174; - at no additional cost to you.
+                            You get paid up front, even though customers have more time to pay. A pre-integrated payment button lets customers pay quickly with Bill Me Later&#174;.
+                            <a href="https:/www.paypal.com/webapps/mpp/promotional-financing" target="_blank">Learn More</a>]]>
+                            </comment>
+                            <config_path>payment/payflow_express_bml/active</config_path>
+                            <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
+                            <attribute type="shared">1</attribute>
+                            <frontend_class>paypal-bml</frontend_class>
+                            <requires>
+                                <field id="enable_paypal_payflow"/>
+                            </requires>
+                        </field>
+                        <group id="paypal_payflow_advertise_bml" translate="label comment" showInDefault="1" showInWebsite="1" sortOrder="22">
+                            <label>Advertise Bill Me Later</label>
+                            <comment>
+                                <![CDATA[<a href="https:/financing.paypal.com/ppfinportal/content/whyUseFinancing" target="_blank">Why Advertise Financing?</a><br/>
+                                <strong>Give your sales a boost when you advertise financing.</strong><br/>PayPal helps turn browsers into buyers with financing
+                                from Bill Me Later&#174;. Your customers have more time to pay, while you get paid up front – at no additional cost to you.
+                                Use PayPal’s free banner ads that let you advertise Bill Me Later&#174; financing as a payment option when your customers check out with PayPal.
+                                The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15%
+                                or more. <a href="https:/financing.paypal.com/ppfinportal/content/forrester" target="_blank">See Details</a>.]]>
+                            </comment>
+                            <field id="bml_publisher_id" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_publisher_id" />
+                            <field id="bml_wizard" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/bml_wizard" />
+                            <group id="paypal_payflow_settings_bml_homepage" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="20">
+                                <label>Home Page</label>
+                                <field id="bml_homepage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_display"/>
+                                <field id="paypal_payflow_bml_homepage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_homepage/bml_homepage_position"/>
+                                <field id="paypal_payflow_bml_homepage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/homepage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_homepage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="paypal_payflow_bml_homepage_size2" extends="payment_us/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_advertise_bml/paypal_payflow_settings_bml_homepage/paypal_payflow_bml_homepage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS</source_model>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_homepage_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                            <group id="paypal_payflow_settings_bml_categorypage" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="30">
+                                <label>Catalog Category Page</label>
+                                <field id="bml_categorypage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_display"/>
+                                <field id="paypal_payflow_bml_categorypage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_categorypage/bml_categorypage_position" />
+                                <field id="paypal_payflow_bml_categorypage_size1" translate="label" sortOrder="30" showInWebsite="1" showInDefault="1" type="select">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/categorypage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_categorypage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="paypal_payflow_bml_categorypage_size2" extends="payment_us/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_advertise_bml/paypal_payflow_settings_bml_categorypage/paypal_payflow_bml_categorypage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS</source_model>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_categorypage_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                            <group id="paypal_payflow_settings_bml_productpage" translate="label" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="40">
+                                <label>Catalog Product Page</label>
+                                <field id="bml_productpage_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_display" />
+                                <field id="paypal_payflow_bml_productpage_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_productpage/bml_productpage_position" />
+                                <field id="paypal_payflow_bml_productpage_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/productpage_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_productpage_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="paypal_payflow_bml_productpage_size2" extends="payment_us/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_advertise_bml/paypal_payflow_settings_bml_productpage/paypal_payflow_bml_productpage_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN</source_model>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_productpage_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                            <group id="paypal_payflow_settings_bml_checkout" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="50">
+                                <label>Checkout Cart Page</label>
+                                <field id="bml_checkout_display" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_display" />
+                                <field id="paypal_payflow_bml_checkout_position" translate="label" extends="payment_all_paypal/express_checkout/express_checkout_required/advertise_bml/settings_bml_checkout/bml_checkout_position" />
+                                <field id="paypal_payflow_bml_checkout_size1" translate="label" type="select" showInDefault="1" showInWebsite="1" sortOrder="30">
+                                    <label>Size</label>
+                                    <config_path>payment/paypal_express_bml/checkout_size</config_path>
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_checkout_position">0</field>
+                                    </depends>
+                                </field>
+                                <field id="paypal_payflow_bml_checkout_size2" extends="payment_us/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_advertise_bml/paypal_payflow_settings_bml_checkout/paypal_payflow_bml_checkout_size1">
+                                    <source_model>Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN</source_model>
+                                    <attribute type="shared">1</attribute>
+                                    <depends>
+                                        <field id="paypal_payflow_bml_checkout_position">1</field>
+                                    </depends>
+                                </field>
+                            </group>
+                        </group>
                     </group>
                     <group id="settings_paypal_payflow" translate="label">
                         <group id="settings_paypal_payflow_advanced" translate="label">
@@ -1656,12 +2336,14 @@
                                 <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model>
                                 <attribute type="shared">1</attribute>
                             </field>
+                            <field id="skip_order_review_step" sortOrder="50" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/skip_order_review_step"/>
                         </group>
                     </group>
                 </group>
             </group>
             <group id="paypal_alternative_payment_methods">
                 <group id="express_checkout_us">
+                    <attribute type="activity_path">payment/paypal_express/active</attribute>
                     <attribute type="activity_path">payment/payflow_express/active</attribute>
                 </group>
             </group>
@@ -1745,6 +2427,7 @@
                             <field id="solution_type" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/solution_type" />
                             <field id="require_billing_address" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/require_billing_address" />
                             <field id="allow_ba_signup" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/allow_ba_signup" />
+                            <field id="skip_order_review_step" extends="payment_all_paypal/express_checkout/settings_ec/settings_ec_advanced/skip_order_review_step" />
                         </group>
                     </group>
                 </group>
@@ -1758,7 +2441,13 @@
                 <frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group</frontend_model>
                 <comment>Add another payment method to your existing solution or as a stand-alone option.</comment>
                 <help_url>https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&amp;subTab=newlineup</help_url>
-                <group id="express_checkout_de" extends="payment_all_paypal/express_checkout"/>
+                <group id="express_checkout_de" extends="payment_all_paypal/express_checkout">
+                    <group id="settings_ec">
+                        <group id="settings_ec_advanced">
+                            <field id="solution_type" showInDefault="0" showInWebsite="0"/>
+                        </group>
+                    </group>
+                </group>
             </group>
         </section>
         <section id="payment_other" extends="payment" showInDefault="0" showInWebsite="0" showInStore="0">
@@ -1777,6 +2466,7 @@
             <group id="paypal_payment_solutions">
                 <group id="wps_other" sortOrder="20"/>
                 <group id="express_checkout_other" sortOrder="50">
+                    <attribute type="activity_path">payment/paypal_express/active</attribute>
                     <attribute type="activity_path">payment/payflow_express/active</attribute>
                 </group>
                 <group id="wpp_ca" extends="payment_all_paypal/wpp" sortOrder="10"/>
diff --git a/app/code/Magento/Paypal/etc/config.xml b/app/code/Magento/Paypal/etc/config.xml
index 6202193ac00..76ef61da6a0 100644
--- a/app/code/Magento/Paypal/etc/config.xml
+++ b/app/code/Magento/Paypal/etc/config.xml
@@ -26,6 +26,7 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd">
     <default>
         <paypal>
+            <bncode>Magento_Cart_Community</bncode>
             <style>
                 <logo>nowAccepting_150x60</logo>
             </style>
@@ -61,7 +62,13 @@
                 <order_valid_period>29</order_valid_period>
                 <child_authorization_number>1</child_authorization_number>
                 <verify_peer>1</verify_peer>
+                <skip_order_review_step>1</skip_order_review_step>
             </paypal_express>
+            <paypal_express_bml>
+                <model>Magento\Paypal\Model\Bml</model>
+                <title>Bill Me Later</title>
+                <group>paypal</group>
+            </paypal_express_bml>
             <paypal_direct>
                 <model>Magento\Paypal\Model\Direct</model>
                 <title>PayPal Payments Pro</title>
@@ -89,6 +96,11 @@
                 <verify_peer>1</verify_peer>
                 <model>Magento\Paypal\Model\PayflowExpress</model>
             </payflow_express>
+            <payflow_express_bml>
+                <model>Magento\Paypal\Model\Payflow\Bml</model>
+                <title>Bill Me Later</title>
+                <group>paypal</group>
+            </payflow_express_bml>
             <payflowpro>
                 <model>Magento\Paypal\Model\Payflowpro</model>
                 <title>Payflow Pro</title>
diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml
index e9488eaa551..ea1b152a85d 100644
--- a/app/code/Magento/Paypal/etc/di.xml
+++ b/app/code/Magento/Paypal/etc/di.xml
@@ -51,4 +51,37 @@
             <argument name="proFactory" xsi:type="object">Magento\Paypal\Model\Payflow\ProFactory</argument>
         </arguments>
     </type>
+    <preference for="Magento\Paypal\Helper\Shortcut\ValidatorInterface" type="Magento\Paypal\Helper\Shortcut\Validator"/>
+    <type name="Magento\Paypal\Block\Express\Shortcut">
+        <arguments>
+            <argument name="paymentMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS</argument>
+            <argument name="startAction" xsi:type="string">paypal/express/start/button/1</argument>
+            <argument name="checkoutType" xsi:type="string">Magento\Paypal\Model\Express\Checkout</argument>
+            <argument name="alias" xsi:type="string">product.info.addtocart.paypal</argument>
+        </arguments>
+    </type>
+    <virtualType name="Magento\Paypal\Block\PayflowExpress\Shortcut" type="Magento\Paypal\Block\Express\Shortcut">
+        <arguments>
+            <argument name="paymentMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS</argument>
+            <argument name="startAction" xsi:type="string">paypal/payflowexpress/start/button/1</argument>
+            <argument name="checkoutType" xsi:type="string">Magento\Paypal\Model\PayflowExpress\Checkout</argument>
+            <argument name="alias" xsi:type="string">product.info.addtocart.payflow</argument>
+        </arguments>
+    </virtualType>
+    <type name="Magento\Paypal\Block\Bml\Shortcut">
+        <arguments>
+            <argument name="paymentMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS</argument>
+            <argument name="startAction" xsi:type="string">paypal/bml/start/button/1</argument>
+            <argument name="bmlMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_BML</argument>
+            <argument name="alias" xsi:type="string">product.info.addtocart.paypalbml</argument>
+        </arguments>
+    </type>
+    <virtualType name="Magento\Paypal\Block\Payflow\Bml\Shortcut" type="Magento\Paypal\Block\Bml\Shortcut">
+        <arguments>
+            <argument name="paymentMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS</argument>
+            <argument name="startAction" xsi:type="string">paypal/payflowbml/start/button/1</argument>
+            <argument name="bmlMethodCode" xsi:type="const">Magento\Paypal\Model\Config::METHOD_WPP_PE_BML</argument>
+            <argument name="alias" xsi:type="string">product.info.addtocart.payflowbml</argument>
+        </arguments>
+    </virtualType>
 </config>
diff --git a/app/code/Magento/Paypal/etc/module.xml b/app/code/Magento/Paypal/etc/module.xml
index 06a0b12f155..a15d87db001 100644
--- a/app/code/Magento/Paypal/etc/module.xml
+++ b/app/code/Magento/Paypal/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Paypal" version="1.6.0.3" active="true">
+    <module name="Magento_Paypal" schema_version="1.6.0.3" active="true">
         <sequence>
             <module name="Magento_Checkout"/>
             <module name="Magento_Sales"/>
diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml
new file mode 100644
index 00000000000..0ecb30227ad
--- /dev/null
+++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+ ?>
+<?php
+/**
+ * @see \Magento\Paypal\Block\Adminhtml\System\Config\BmlApiWizard
+ */
+?>
+<div class="pp-buttons-container">
+    <button onclick="javascript:window.open('<?php echo $this->getButtonUrl()?>', 'bmlapiwizard','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, ,left=100, top=100, width=550, height=550'); return false;" class="scalable" type="button" id="<?php echo $this->getHtmlId() ?>">
+        <span><span><span><?php echo $this->escapeHtml($this->getButtonLabel()); ?></span></span></span>
+    </button>
+</div>
\ No newline at end of file
diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml
index 3ff6aca7164..231c027d4a4 100644
--- a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml
+++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml
@@ -24,7 +24,21 @@
  */
 -->
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
-    <referenceContainer name="right">
+    <referenceContainer name="content.aside">
         <block class="Magento\Paypal\Block\Logo" name="paypal.partner.right.logo" template="partner/logo.phtml"/>
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.right.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">categorypage</argument>
+                <argument name="position" xsi:type="number">1</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+    <referenceContainer name="top.container">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.center.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">categorypage</argument>
+                <argument name="position" xsi:type="number">0</argument>
+            </arguments>
+        </block>
     </referenceContainer>
 </layout>
diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml
new file mode 100644
index 00000000000..206662b17aa
--- /dev/null
+++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceContainer name="top.container">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.center.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">productpage</argument>
+                <argument name="position" xsi:type="number">0</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+    <referenceContainer name="product.info.addtocart">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.right.logo" after="product.info.addtocart.paypal" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">productpage</argument>
+                <argument name="position" xsi:type="number">1</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+</layout>
diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml
new file mode 100644
index 00000000000..ff8df46b11f
--- /dev/null
+++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
+    <referenceContainer name="top.container">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.center.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">checkout</argument>
+                <argument name="position" xsi:type="number">0</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+    <referenceContainer name="checkout.cart.methods">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.right.logo" after="checkout.cart.methods.onepage.bottom" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">checkout</argument>
+                <argument name="position" xsi:type="number">1</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+</layout>
diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml
index f8ed5a58e7f..f80df51b352 100644
--- a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml
+++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml
@@ -30,4 +30,12 @@
     <referenceContainer name="content">
         <block class="Magento\Framework\View\Element\Template" name="checkout.onepage.paypal.js" after="checkout.onepage" template="Magento_Paypal::onepage.phtml"/>
     </referenceContainer>
+    <referenceContainer name="top.container">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.center.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">checkout</argument>
+                <argument name="position" xsi:type="number">0</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
 </layout>
diff --git a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml
index 3ff6aca7164..e8f4d422533 100644
--- a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml
+++ b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml
@@ -26,5 +26,19 @@
 <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Core/etc/layout_single.xsd">
     <referenceContainer name="right">
         <block class="Magento\Paypal\Block\Logo" name="paypal.partner.right.logo" template="partner/logo.phtml"/>
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.right.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">homepage</argument>
+                <argument name="position" xsi:type="number">1</argument>
+            </arguments>
+        </block>
+    </referenceContainer>
+    <referenceContainer name="top.container">
+        <block class="Magento\Paypal\Block\Bml\Banners" name="bml.center.logo" template="bml.phtml">
+            <arguments>
+                <argument name="section" xsi:type="string">homepage</argument>
+                <argument name="position" xsi:type="number">0</argument>
+            </arguments>
+        </block>
     </referenceContainer>
 </layout>
diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml
index 4629e28332c..373939fdfb2 100644
--- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml
+++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml
@@ -36,10 +36,6 @@
     </referenceBlock>
     <referenceContainer name="content">
         <block class="Magento\Paypal\Block\Express\Review" name="paypal.express.review" template="express/review.phtml">
-            <block class="Magento\Paypal\Block\Express\Review\Billing" name="express.review.billing" as="billing"
-                   template="express/review/address.phtml" cacheable="false"/>
-            <block class="Magento\Paypal\Block\Express\Review\Shipping" name="express.review.shipping" as="shipping"
-                   template="express/review/address.phtml" cacheable="false"/>
             <block class="Magento\Paypal\Block\Express\Review" name="express.review.shipping.method"
                    as="shipping_method" template="express/review/shipping/method.phtml"/>
             <block class="Magento\Paypal\Block\Express\Review\Details" name="paypal.express.review.details" as="details"
diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml
index c4e09be89b6..536c740fec9 100644
--- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml
+++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml
@@ -32,10 +32,12 @@
     </referenceBlock>
     <referenceContainer name="content">
         <block class="Magento\Paypal\Block\Express\Review" name="paypal.express.review"
-               template="payflowexpress/review.phtml">
+               template="express/review.phtml">
             <action method="setControllerPath">
                 <argument name="prefix" xsi:type="string">paypal/payflowexpress</argument>
             </action>
+            <block class="Magento\Paypal\Block\Express\Review" name="express.review.shipping.method"
+                   as="shipping_method" template="express/review/shipping/method.phtml"/>
             <block class="Magento\Paypal\Block\Express\Review\Details" name="paypal.express.review.details" as="details"
                    template="express/review/details.phtml">
                 <block class="Magento\Framework\View\Element\RendererList" name="checkout.onepage.review.item.renderers" as="renderer.list" />
diff --git a/app/code/Magento/Paypal/view/frontend/templates/bml.phtml b/app/code/Magento/Paypal/view/frontend/templates/bml.phtml
new file mode 100644
index 00000000000..26448addf9d
--- /dev/null
+++ b/app/code/Magento/Paypal/view/frontend/templates/bml.phtml
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+ ?>
+<?php
+/**
+ * @see \Magento\Paypal\Block\Bml\Banners
+ */
+?>
+<div class="paypal-logo">
+    <script type="text/javascript" data-pp-pubid="<?php echo $this->escapeHtml($this->getPublisherId()) ?>" data-pp-placementtype="<?php echo $this->escapeHtml($this->getSize()) ?>"> (function (d, t) {
+            "use strict";
+            var s = d.getElementsByTagName(t)[0], n = d.createElement(t);
+            n.src = "//paypal.adtag.where.com/merchant.js";
+            s.parentNode.insertBefore(n, s);
+        }(document, "script"));
+    </script>
+</div>
\ No newline at end of file
diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml
index af05fd0c913..dd3f730f570 100644
--- a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml
+++ b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml
@@ -23,89 +23,123 @@
  */
 /** @var $this \Magento\Paypal\Block\Express\Review */
 
-$billingBlock = $this->getChildBlock('billing')->setFieldNamePrefix('billing')->setHideEmailAddress(true);
-$shippingAddress = $this->getShippingAddress();
 ?>
 <hgroup class="page title">
     <h1 class="title"><span class="base"><?php echo __('Review Order') ?></span></h1>
 </hgroup>
-<?php echo $this->getLayout()->getMessagesBlock()->toHtml() ?>
 <div class="paypal review view">
-    <div class="paypal subtitle caption"><strong>Please confirm your addresses</strong></div>
+    <?php if ($this->getShippingAddress()): ?>
+        <div class="block shipping information">
+            <div class="title"><strong><?php echo __('Shipping Information') ?></strong></div>
+            <div class="content">
+                <div class="box shipping address">
+                    <strong class="subtitle">
+                        <?php echo __('Shipping Address') ?>
+                        <?php if ($this->getCanEditShippingAddress()): ?>
+                            <a href="<?php echo $this->getEditUrl() ?>"
+                               class="action edit"><span><?php echo __('Edit') ?></span></a>
+                        <?php endif; ?>
+                    </strong>
 
-    <form method="post" id="order-review-form" action="<?php echo $this->getPlaceOrderUrl() ?>"
-          class="form paypal review">
-        <?php if (!$billingBlock->isCustomerLoggedIn()): ?>
-            <fieldset class="fieldset customer email">
-                <legend class="legend"><span><?php echo __('Customer Information') ?></span></legend>
-                <br>
-
-                <div id="customer-info-form" class="field email required">
-                    <label for="customer:email" class="label"><?php echo __('Email Address') ?></label>
-
-                    <div class="control">
-                        <input type="email" name="customer-email" id="customer:email"
-                               value="<?php echo $this->escapeHtml($billingBlock->getAddress()->getEmail()) ?>"
-                               title="<?php echo __('Email Address') ?>" class="input-text"/>
+                    <div class="content">
+                        <address><?php echo $this->renderAddress($this->getShippingAddress()) ?></address>
                     </div>
                 </div>
-            </fieldset>
-        <?php endif ?>
 
-        <fieldset class="fieldset billing address" id="billing-address">
-            <legend class="legend"><span><?php echo __('Billing Address') ?></span></legend>
-            <br>
-            <?php if ($shippingAddress): ?>
-                <?php echo $billingBlock->setShowAsShippingCheckbox(true)->toHtml(); ?>
-            <?php else: ?>
-                <?php echo $billingBlock->toHtml(); ?>
-            <?php endif; ?>
-        </fieldset>
+                <div class="box shipping method">
+                    <strong class="subtitle"><?php echo __('Shipping Method') ?></strong>
 
-        <?php if ($shippingAddress): ?>
-            <fieldset class="fieldset shipping address" id="shipping-address">
-                <legend class="legend"><span><?php echo __('Shipping Address') ?></span></legend>
-                <br>
-                <?php echo $this->getChildBlock('shipping')->setFieldNamePrefix('shipping')->setHideEmailAddress(true)->toHtml(); ?>
-            </fieldset>
+                    <div class="content">
+                        <form method="post" id="shipping-method-form"
+                              action="<?php echo $this->escapeHtml($this->getShippingMethodSubmitUrl()) ?>"
+                              class="form">
+                            <?php if ($this->getCanEditShippingMethod() || !$this->getCurrentShippingRate()): ?>
+                                <?php if ($groups = $this->getShippingRateGroups()): ?>
+                                    <?php $currentRate = $this->getCurrentShippingRate(); ?>
+                                    <div class="field shipping required">
+                                        <select name="shipping_method" id="shipping-method" class="select">
+                                            <?php if (!$currentRate): ?>
+                                                <option value="">
+                                                    <?php echo __('Please select a shipping method...') ?>
+                                                </option>
+                                            <?php endif; ?>
+                                            <?php foreach ($groups as $code => $rates): ?>
+                                                <optgroup
+                                                    label="<?php echo $this->escapeHtml($this->getCarrierName($code)) ?>">
+                                                    <?php foreach ($rates as $rate): ?>
+                                                        <option
+                                                            value="<?php echo $this->renderShippingRateValue($rate) ?>"<?php echo ($currentRate === $rate) ? ' selected="selected"' : ''; ?>>
+                                                            <?php echo $this->renderShippingRateOption($rate) ?>
+                                                        </option>
+                                                    <?php endforeach; ?>
+                                                </optgroup>
+                                            <?php endforeach; ?>
+                                        </select>
+                                    </div>
+                                    <div class="actions">
+                                        <button id="update-shipping-method-submit" type="submit" class="action update">
+                                            <span><?php echo __('Update Shipping Method') ?></span></button>
+                                    </div>
+                                <?php else: ?>
+                                    <p><?php echo __('Sorry, no quotes are available for this order at this time.') ?></p>
+                                <?php endif; ?>
+                            <?php else: ?>
+                                <p><?php echo $this->renderShippingRateOption($this->getCurrentShippingRate()) ?></p>
+                            <?php endif; ?>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    <?php endif; ?>
 
-            <fieldset class="fieldset shipping method">
-                <legend class="legend"><span><?php echo __('Shipping Method') ?></span></legend>
-                <br>
-                <?php echo $this->getChildBlock('shipping_method')->toHtml(); ?>
-            </fieldset>
-        <?php endif; ?>
+    <div class="block billing information">
+        <div class="title"><strong><?php echo __('Billing Information') ?></strong></div>
+        <div class="content">
+            <div class="box billing">
+                <strong class="subtitle">
+                    <?php echo __('Payment Method') ?>
+                    <?php if ($this->getEditUrl()): ?><a href="<?php echo $this->getEditUrl() ?>" class="action edit">
+                        <span><?php echo __('Edit Payment Information') ?></span></a><?php endif ?>
+                </strong>
 
-        <div class="paypal review items">
-            <div class="paypal subtitle caption">
-                <strong><?php echo __('Items in Your Shopping Cart') ?></strong>
-                <a href="<?php echo $this->getUrl('checkout/cart') ?>"
-                   class="action edit"><?php echo __('Edit Shopping Cart') ?></a>
+                <div class="content">
+                    <?php echo $this->escapeHtml($this->getPaymentMethodTitle()) ?>
+                </div>
             </div>
+        </div>
+    </div>
 
-            <div id="details-reload">
-                <?php echo $this->getChildHtml('details') ?>
-            </div>
+    <div class="paypal review items">
+        <div class="paypal subtitle caption">
+            <strong><?php echo __('Items in Your Shopping Cart') ?></strong>
+            <a href="<?php echo $this->getUrl('checkout/cart') ?>"
+               class="action edit"><span><?php echo __('Edit Shopping Cart') ?></span></a>
         </div>
 
-        <?php echo $this->getChildHtml('agreements'); ?>
-        <div class="actions" id="review-buttons-container">
-            <button type="button" id="review-button" value="<?php echo __('Place Order') ?>" class="action checkout">
-                <span><?php echo __('Place Order') ?></span></button>
-            <button type="button" id="review-submit" value="<?php echo __('Place Order') ?>" class="action checkout">
-                <span><?php echo __('Place Order') ?></span></button>
-            <button type="button" id="update-order" class="action update">
-                <span><?php echo __('Update Order Data') ?></span></button>
-            <span class="please-wait load indicator" id="review-please-wait" style="display: none;" data-text="<?php echo __('Submitting order information...') ?>">
-               <span><?php echo __('Submitting order information...') ?></span>
-            </span>
+        <div id="details-reload">
+            <?php echo $this->getChildHtml('details') ?>
         </div>
-    </form>
+
+        <form method="post" id="order-review-form" action="<?php echo $this->getPlaceOrderUrl() ?>" class="form">
+            <?php echo $this->getChildHtml('agreements'); ?>
+            <div class="actions" id="review-buttons-container">
+                <button type="button" id="review-button" value="<?php echo __('Place Order') ?>"
+                        class="action checkout"><span><?php echo __('Place Order') ?></span></button>
+                <button type="button" id="review-submit" value="<?php echo __('Place Order') ?>"
+                        class="action checkout"><span><?php echo __('Place Order') ?></span></button>
+                <span class="please-wait load indicator" id="review-please-wait" style="display: none;" data-text="<?php echo __('Submitting order information...') ?>">
+                   <span><?php echo __('Submitting order information...') ?></span>
+                </span>
+            </div>
+        </form>
+    </div>
 </div>
 <script type="text/javascript">
     jQuery('#order-review-form').mage('validation', {}).mage('orderReview', {
+        shippingSubmitFormSelector: '#shipping-method-form',
+        shippingSelector: '#shipping-method',
         shippingMethodUpdateUrl: '<?php echo $this->escapeHtml($this->getUpdateShippingMethodsUrl()) ?>',
-        updateOrderSubmitUrl: '<?php echo $this->escapeHtml($this->getUpdateOrderSubmitUrl()) ?>',
         isAjax: <?php echo $this->getUseAjax() ? 'true' : 'false' ?>
     });
 </script>
diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml
deleted file mode 100644
index 38c73911088..00000000000
--- a/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Academic Free License (AFL 3.0)
- * that is bundled with this package in the file LICENSE_AFL.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/afl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
- */
-?>
-<?php
-/**
- * @var \Magento\Paypal\Block\Express\Review\Shipping|\Magento\Paypal\Block\Express\Review\Billing $this
- */
-?>
-<?php $prefix = $this->getFieldNamePrefix(); ?>
-<input type="hidden" name="<?php echo $prefix ?>[address_id]" value="<?php echo $this->getAddress()->getId() ?>"
-       id="<?php echo $prefix ?>:address_id"/>
-<?php
-/** @var \Magento\Customer\Block\Widget\Name $nameWidget */
-$nameWidget = $this->getLayout()->createBlock('Magento\Customer\Block\Widget\Name');
-$widgetObject = $this->getAddress()->getFirstname() ? $this->getAddress() : $this->getQuote()->getCustomerData();
-echo $nameWidget
-    ->setObject($widgetObject)
-    ->setForceUseCustomerRequiredAttributes(!$this->isCustomerLoggedIn())
-    ->setFieldIdFormat($prefix . ':%s')
-    ->setFieldNameFormat($prefix . '[%s]')
-    ->toHtml()
-?>
-
-<div class="field company">
-    <label for="<?php echo $prefix ?>:company" class="label"><span><?php echo __('Company') ?></span></label>
-
-    <div class="control">
-        <input type="text" id="<?php echo $prefix ?>:company" name="<?php echo $prefix ?>[company]"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getCompany()) ?>"
-               title="<?php echo __('Company') ?>"
-               class="input-text <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('company') ?>"/>
-    </div>
-</div>
-
-<?php if (!$this->isCustomerLoggedIn() && !$this->getHideEmailAddress()): ?>
-    <div class="field email required">
-        <label for="<?php echo $prefix ?>:email" class="label"><span><?php echo __('Email Address') ?></span></label>
-
-        <div class="control">
-            <input type="email" name="<?php echo $prefix ?>[email]" id="<?php echo $prefix ?>:email"
-                   value="<?php echo $this->escapeHtml($this->getAddress()->getEmail()) ?>"
-                   title="<?php echo __('Email Address') ?>" class="input-text validate-email required-entry"/>
-        </div>
-    </div>
-<?php endif; ?>
-
-<?php $_streetValidationClass = $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?>
-<div class="field street required">
-    <label for="<?php echo $prefix ?>:street1" class="label"><span><?php echo __('Address') ?></span></label>
-
-    <div class="control">
-        <input type="text" title="<?php echo __('Street Address') ?>" name="<?php echo $prefix ?>[street][]"
-               id="<?php echo $prefix ?>:street1"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getStreet(1)) ?>"
-               class="input-text required-entry <?php echo $_streetValidationClass ?>"/>
-        <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?>
-        <?php for ($_i = 2, $_n = $this->helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i <= $_n; $_i++): ?>
-            <div class="nested">
-                <input type="text" title="<?php echo __('Street Address %1', $_i) ?>"
-                       name="<?php echo $prefix ?>[street][]" id="<?php echo $prefix ?>:street<?php echo $_i ?>"
-                       value="<?php echo $this->escapeHtml($this->getAddress()->getStreet($_i)) ?>"
-                       class="input-text <?php echo $_streetValidationClass ?>"/>
-            </div>
-        <?php endfor; ?>
-    </div>
-</div>
-
-<?php if ($this->helper('Magento\Customer\Helper\Address')->isVatAttributeVisible()) : ?>
-    <div class="field vat">
-        <label for="<?php echo $prefix ?>:vat_id" class="label"><span><?php echo __('VAT Number') ?></span></label>
-
-        <div class="control">
-            <input type="text" id="<?php echo $prefix ?>:vat_id" name="<?php echo $prefix ?>[vat_id]"
-                   value="<?php echo $this->escapeHtml($this->getAddress()->getVatId()) ?>"
-                   title="<?php echo __('VAT Number') ?>"
-                   class="input-text <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('vat_id') ?>"/>
-        </div>
-    </div>
-<?php endif; ?>
-
-<div class="field city required">
-    <label for="<?php echo $prefix ?>:city" class="label"><span><?php echo __('City') ?></span></label>
-
-    <div class="control">
-        <input type="text" title="<?php echo __('City') ?>" name="<?php echo $prefix ?>[city]"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getCity()) ?>"
-               class="input-text required-entry <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('city') ?>"
-               id="<?php echo $prefix ?>:city"/>
-    </div>
-</div>
-
-<div class="field regionid required">
-    <label for="<?php echo $prefix ?>:region_id" class="label"><span><?php echo __('State/Province') ?></span></label>
-
-    <div class="control">
-        <select id="<?php echo $prefix ?>:region_id" name="<?php echo $prefix ?>[region_id]"
-                title="<?php echo __('State/Province') ?>" class="validate-select required-entry" style="display:none;">
-            <option value=""><?php echo __('Please select region, state or province') ?></option>
-        </select>
-        <input type="text" id="<?php echo $prefix ?>:region" name="<?php echo $prefix ?>[region]"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getRegion()) ?>"
-               title="<?php echo __('State/Province') ?>"
-               class="input-text <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('region') ?>"
-               style="display:none;"/>
-    </div>
-</div>
-
-<div class="field postcode required">
-    <label for="<?php echo $prefix ?>:postcode" class="label"><span><?php echo __('Zip/Postal Code') ?></span></label>
-
-    <div class="control">
-        <input type="text" title="<?php echo __('Zip/Postal Code') ?>" name="<?php echo $prefix ?>[postcode]"
-               id="<?php echo $prefix ?>:postcode"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getPostcode()) ?>"
-               class="input-text validate-zip-international required-entry <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('postcode') ?>"/>
-    </div>
-</div>
-
-<div class="field country_id required">
-    <label for="<?php echo $prefix ?>:country_id" class="label"><span><?php echo __('Country') ?></span></label>
-
-    <div class="control">
-        <?php echo $this->getCountryHtmlSelect($prefix) ?>
-    </div>
-</div>
-
-<div class="field telephone required">
-    <label for="<?php echo $prefix ?>:telephone" class="label"><span><?php echo __('Telephone') ?></span></label>
-
-    <div class="control">
-        <input type="text" name="<?php echo $prefix ?>[telephone]"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getTelephone()) ?>"
-               title="<?php echo __('Telephone') ?>"
-               class="input-text required-entry <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('telephone') ?>"
-               id="<?php echo $prefix ?>:telephone"/>
-    </div>
-</div>
-
-<div class="field fax">
-    <label for="<?php echo $prefix ?>:fax" class="label"><span><?php echo __('Fax') ?></span></label>
-
-    <div class="control">
-        <input type="text" name="<?php echo $prefix ?>[fax]"
-               value="<?php echo $this->escapeHtml($this->getAddress()->getFax()) ?>" title="<?php echo __('Fax') ?>"
-               class="input-text <?php echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('fax') ?>"
-               id="<?php echo $prefix ?>:fax"/>
-    </div>
-</div>
-
-<?php echo $this->getChildHtml('form.additional.info'); ?>
-<?php if ($this->getShowAsShippingCheckbox()): ?>
-    <div class="field choice as_shipping">
-        <input type="checkbox" name="<?php echo $prefix ?>[as_shipping]" class="checkbox" value="1"
-               title="<?php echo __('Same as shipping') ?>" id="<?php echo $prefix ?>:as_shipping"
-               <?php if ($this->getAddress()->getSameAsBilling()): ?>checked="checked"<?php endif; ?>/>
-        <label for="<?php echo $prefix ?>:as_shipping"
-               class="label"><span><?php echo __('Same as shipping') ?></span></label>
-    </div>
-<?php endif; ?>
-
-<script type="text/javascript">
-    (function ($) {
-        $('#<?php echo $prefix ?>\\:country_id').mage('regionUpdater', {
-            optionalRegionAllowed: <?php echo ($this->getConfig('general/region/display_all')? 'true' : 'false'); ?>,
-            regionListId: '#<?php echo $prefix ?>\\\:region_id',
-            regionInputId: '#<?php echo $prefix ?>\\\:region',
-            postcodeId: '#<?php echo $prefix ?>\\\:postcode',
-            regionJson: <?php echo $this->helper('Magento\Directory\Helper\Data')->getRegionJson() ?>,
-            defaultRegion: "<?php echo $this->getAddress()->getRegionId() ?>",
-            countriesWithOptionalZip: <?php echo $this->helper('Magento\Directory\Helper\Data')->getCountriesWithOptionalZip(true) ?>
-        });
-    })(jQuery);
-</script>
diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml
index b903823ef7a..e076babdc28 100644
--- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml
+++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml
@@ -35,8 +35,8 @@ if ($this->isOrPositionBefore()) {
     $labelPosition = ' after';
 }
 ?>
-<div data-label="or" class="paypal checkout <?php echo $labelPosition ?> paypal-logo">
-    <?php $shortcutHtmlId = $this->getShortcutHtmlId() ?>
+<?php $shortcutHtmlId = $this->getShortcutHtmlId() ?>
+<div data-label="or" class="paypal checkout <?php echo $labelPosition ?> paypal-logo <?php echo $shortcutHtmlId ?>">
     <input type="image" data-action="checkout-form-submit" data-checkout-url="<?php echo $this->getCheckoutUrl() ?>"
            src="<?php echo $this->getImageUrl() ?>"
            alt="<?php echo __('Checkout with PayPal'); ?>"
@@ -50,10 +50,14 @@ if ($this->isOrPositionBefore()) {
         $confirmationUrl = $this->getConfirmationUrl();
         $isInCatalogProduct = $this->getIsInCatalogProduct();
     endif; ?>
+    <?php if ($this->getAdditionalLinkImage()): ?>
+        <?php $linkImage = $this->getAdditionalLinkImage() ?>
+        <a href="<?php echo $linkImage['href']?>"><img src="<?php echo $linkImage['src']?>" /></a>
+    <?php endif; ?>
     <script type="text/javascript">
         (function ($) {
             head.js("<?php echo $this->getViewFileUrl('Magento_Paypal::js/paypal-checkout.js') ?>", head.ready(function () {
-                $('.paypal-logo').paypalCheckout({
+                $('.paypal-logo.<?php echo $shortcutHtmlId ?>').paypalCheckout({
                     confirmMessage: "<?php echo $this->escapeJsQuote($this->getConfirmationMessage())?>",
                     confirmUrl: "<?php echo !empty($confirmationUrl) ? $confirmationUrl : false ?>",
                     isCatalogProduct: "<?php echo !empty($isInCatalogProduct) ? $isInCatalogProduct : false ?>",
diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowexpress/review.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowexpress/review.phtml
deleted file mode 100644
index 351e11ab5d5..00000000000
--- a/app/code/Magento/Paypal/view/frontend/templates/payflowexpress/review.phtml
+++ /dev/null
@@ -1,158 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Academic Free License (AFL 3.0)
- * that is bundled with this package in the file LICENSE_AFL.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/afl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
- */
-/** @var $this \Magento\Paypal\Block\Express\Review */
-?>
-<hgroup class="page title">
-    <h1 class="title"><span class="base"><?php echo __('Review Order') ?></span></h1>
-</hgroup>
-<div class="paypal review view">
-    <?php if ($this->getShippingAddress()): ?>
-        <div class="block shipping information">
-            <div class="title"><strong><?php echo __('Shipping Information') ?></strong></div>
-            <div class="content">
-                <div class="box shipping address">
-                    <strong class="subtitle">
-                        <?php echo __('Shipping Address') ?>
-                        <?php if ($this->getCanEditShippingAddress()): ?>
-                            <a href="<?php echo $this->getEditUrl() ?>"
-                               class="action edit"><span><?php echo __('Change Shipping Address') ?></span></a>
-                        <?php endif; ?>
-                    </strong>
-
-                    <div class="content">
-                        <address><?php echo $this->renderAddress($this->getShippingAddress()) ?></address>
-                    </div>
-                </div>
-
-                <div class="box shipping method">
-                    <strong class="subtitle"><?php echo __('Shipping Method') ?></strong>
-
-                    <div class="content">
-                        <form method="post" id="shipping-method-form"
-                              action="<?php echo $this->escapeHtml($this->getShippingMethodSubmitUrl()) ?>"
-                              class="form">
-                            <?php if ($this->getCanEditShippingMethod() || !$this->getCurrentShippingRate()): ?>
-                                <?php if ($groups = $this->getShippingRateGroups()): ?>
-                                    <?php $currentRate = $this->getCurrentShippingRate(); ?>
-                                    <div class="field shipping required">
-                                        <select name="shipping_method" id="shipping-method" class="select">
-                                            <?php if (!$currentRate): ?>
-                                                <option value="">
-                                                    <?php echo __('Please select a shipping method...') ?>
-                                                </option>
-                                            <?php endif; ?>
-                                            <?php foreach ($groups as $code => $rates): ?>
-                                                <optgroup
-                                                    label="<?php echo $this->escapeHtml($this->getCarrierName($code)) ?>">
-                                                    <?php foreach ($rates as $rate): ?>
-                                                        <option
-                                                            value="<?php echo $this->renderShippingRateValue($rate) ?>"<?php echo ($currentRate === $rate) ? ' selected="selected"' : ''; ?>>
-                                                            <?php echo $this->renderShippingRateOption($rate) ?>
-                                                        </option>
-                                                    <?php endforeach; ?>
-                                                </optgroup>
-                                            <?php endforeach; ?>
-                                        </select>
-                                    </div>
-                                    <div class="actions">
-                                        <button id="update-shipping-method-submit" type="submit" class="action update">
-                                            <span><?php echo __('Update Shipping Method') ?></span></button>
-                                    </div>
-                                <?php else: ?>
-                                    <p><?php echo __('Sorry, no quotes are available for this order at this time.') ?></p>
-                                <?php endif; ?>
-                            <?php else: ?>
-                                <p><?php echo $this->renderShippingRateOption($this->getCurrentShippingRate()) ?></p>
-                            <?php endif; ?>
-                        </form>
-                    </div>
-                </div>
-            </div>
-        </div>
-    <?php endif; ?>
-
-    <div class="block billing information">
-        <div class="title"><strong><?php echo __('Billing Information') ?></strong></div>
-        <div class="content">
-            <div class="box billing">
-                <strong class="subtitle">
-                    <?php echo __('Payment Method') ?>
-                    <?php if ($this->getEditUrl()): ?><a href="<?php echo $this->getEditUrl() ?>" class="action edit">
-                        <span><?php echo __('Change Payment Method') ?></span></a><?php endif ?>
-                </strong>
-
-                <div class="content">
-                    <?php echo $this->escapeHtml($this->getPaymentMethodTitle()) ?>
-                </div>
-            </div>
-
-            <div class="box billing">
-                <strong class="subtitle"><?php echo __('Billing Address') ?></strong>
-
-                <div class="content">
-                    <address>
-                        <?php echo $this->renderAddress($this->getBillingAddress()) ?><br/>
-                        <?php echo __('Payer Email: %1', $this->getBillingAddress()->getEmail()) ?>
-                    </address>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="paypal review items">
-        <div class="paypal subtitle caption">
-            <strong><?php echo __('Items in Your Shopping Cart') ?></strong>
-            <a href="<?php echo $this->getUrl('checkout/cart') ?>"
-               class="action edit"><span><?php echo __('Edit Shopping Cart') ?></span></a>
-        </div>
-
-        <div id="details-reload">
-            <?php echo $this->getChildHtml('details') ?>
-        </div>
-
-        <form method="post" id="order-review-form" action="<?php echo $this->getPlaceOrderUrl() ?>" class="form">
-            <?php echo $this->getChildHtml('agreements'); ?>
-            <div class="actions" id="review-buttons-container">
-                <button type="button" id="review-button" value="<?php echo __('Place Order') ?>"
-                        class="action checkout"><span><?php echo __('Place Order') ?></span></button>
-                <button type="button" id="review-submit" value="<?php echo __('Place Order') ?>"
-                        class="action checkout"><span><?php echo __('Place Order') ?></span></button>
-                <button type="button" id="update-order" class="action update">
-                    <span><?php echo __('Update Order Data') ?></span></button>
-                <span class="please-wait load indicator" id="review-please-wait" style="display: none;" data-text="<?php echo __('Submitting order information...') ?>">
-                   <span><?php echo __('Submitting order information...') ?></span>
-                </span>
-            </div>
-        </form>
-    </div>
-</div>
-<script type="text/javascript">
-    jQuery('#order-review-form').mage('validation', {}).mage('orderReview', {
-        shippingSubmitFormSelector: '#shipping-method-form',
-        shippingSelector: '#shipping-method',
-        shippingMethodUpdateUrl: '<?php echo $this->escapeHtml($this->getUpdateShippingMethodsUrl()) ?>',
-        updateOrderSubmitUrl: '<?php echo $this->escapeHtml($this->getUpdateOrderSubmitUrl()) ?>',
-        isAjax: <?php echo $this->getUseAjax() ? 'true' : 'false' ?>
-    });
-</script>
diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml
index e719e25e9cf..2c3e93d3bf4 100644
--- a/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml
+++ b/app/code/Magento/Paypal/view/frontend/templates/payment/mark.phtml
@@ -33,5 +33,7 @@
      alt="<?php echo __('Acceptance Mark') ?>" class="paypal icon"/>
 <a href="<?php echo $this->getPaymentAcceptanceMarkHref() ?>"
    onclick="javascript:window.open('<?php echo $this->getPaymentAcceptanceMarkHref() ?>','olcwhatispaypal','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, ,left=0, top=0, width=400, height=350'); return false;"
-   class="action paypal about"><?php echo __('What is PayPal?') ?></a>
+   class="action paypal about">
+    <?php if($this->getPaymentWhatIs()) {echo __($this->getPaymentWhatIs());} else {echo __('What is PayPal?');} ?>
+</a>
 <!-- PayPal Logo -->
diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml
index 90455c4ea3c..293affff4b1 100644
--- a/app/code/Magento/Persistent/etc/module.xml
+++ b/app/code/Magento/Persistent/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Persistent" version="1.0.0.0" active="true">
+    <module name="Magento_Persistent" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Checkout"/>
         </sequence>
diff --git a/app/code/Magento/ProductAlert/etc/module.xml b/app/code/Magento/ProductAlert/etc/module.xml
index 5a58fa1ad0c..301a9234e2d 100644
--- a/app/code/Magento/ProductAlert/etc/module.xml
+++ b/app/code/Magento/ProductAlert/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_ProductAlert" version="1.6.0.0" active="true">
+    <module name="Magento_ProductAlert" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Customer"/>
diff --git a/app/code/Magento/RecurringPayment/etc/module.xml b/app/code/Magento/RecurringPayment/etc/module.xml
index 7a0aa47c124..bef5e072ef2 100644
--- a/app/code/Magento/RecurringPayment/etc/module.xml
+++ b/app/code/Magento/RecurringPayment/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_RecurringPayment" version="1.0.0.0" active="true">
+    <module name="Magento_RecurringPayment" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Magento_Sales"/>
             <module name="Magento_User"/>
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
index 8162a1c42ae..17bdbb06052 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
@@ -217,6 +217,7 @@ class Sales extends AbstractReport
     public function exportTaxExcelAction()
     {
         $fileName = 'tax.xml';
+        /** @var \Magento\Reports\Block\Adminhtml\Sales\Tax\Grid $grid */
         $grid = $this->_view->getLayout()->createBlock('Magento\Reports\Block\Adminhtml\Sales\Tax\Grid');
         $this->_initReportAction($grid);
         return $this->_fileFactory->create($fileName, $grid->getExcelFile($fileName), \Magento\Framework\App\Filesystem::VAR_DIR);
diff --git a/app/code/Magento/Reports/Model/Event/Observer.php b/app/code/Magento/Reports/Model/Event/Observer.php
index 01a86000d09..ceb50ae3be8 100644
--- a/app/code/Magento/Reports/Model/Event/Observer.php
+++ b/app/code/Magento/Reports/Model/Event/Observer.php
@@ -97,8 +97,7 @@ class Observer
     {
         if (is_null($subjectId)) {
             if ($this->_customerSession->isLoggedIn()) {
-                $customer = $this->_customerSession->getCustomer();
-                $subjectId = $customer->getId();
+                $subjectId = $this->_customerSession->getCustomerId();
             } else {
                 $subjectId = $this->_logVisitor->getId();
                 $subtype = 1;
diff --git a/app/code/Magento/Reports/etc/module.xml b/app/code/Magento/Reports/etc/module.xml
index 115fde5d242..ea51baa5954 100644
--- a/app/code/Magento/Reports/etc/module.xml
+++ b/app/code/Magento/Reports/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Reports" version="1.6.0.0.2" active="true">
+    <module name="Magento_Reports" schema_version="1.6.0.0.2" active="true">
         <sequence>
             <module name="Magento_Customer"/>
             <module name="Magento_Catalog"/>
diff --git a/app/code/Magento/RequireJs/etc/module.xml b/app/code/Magento/RequireJs/etc/module.xml
index 8e381f0ce46..a380d363d63 100644
--- a/app/code/Magento/RequireJs/etc/module.xml
+++ b/app/code/Magento/RequireJs/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_RequireJs" version="1.0.0.0" active="true">
+    <module name="Magento_RequireJs" schema_version="1.0.0.0" active="true">
         <depends>
             <module name="Magento_Theme"/>
         </depends>
diff --git a/app/code/Magento/Review/etc/module.xml b/app/code/Magento/Review/etc/module.xml
index bc399c761d0..63fd32ebe5b 100644
--- a/app/code/Magento/Review/etc/module.xml
+++ b/app/code/Magento/Review/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Review" version="1.6.0.0" active="true">
+    <module name="Magento_Review" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Core"/>
diff --git a/app/code/Magento/Rss/etc/module.xml b/app/code/Magento/Rss/etc/module.xml
index cd63a0e8e5e..31dc0c6d015 100644
--- a/app/code/Magento/Rss/etc/module.xml
+++ b/app/code/Magento/Rss/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Rss" version="1.6.0.0" active="true">
+    <module name="Magento_Rss" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_CatalogInventory"/>
diff --git a/app/code/Magento/Rule/etc/module.xml b/app/code/Magento/Rule/etc/module.xml
index 3ffa4a7cf2c..a413a2a5053 100644
--- a/app/code/Magento/Rule/etc/module.xml
+++ b/app/code/Magento/Rule/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Rule" version="1.6.0.0" active="true">
+    <module name="Magento_Rule" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Sales/Block/Order/History.php b/app/code/Magento/Sales/Block/Order/History.php
index 1a9403726cd..5b974af37e4 100644
--- a/app/code/Magento/Sales/Block/Order/History.php
+++ b/app/code/Magento/Sales/Block/Order/History.php
@@ -80,7 +80,7 @@ class History extends \Magento\Framework\View\Element\Template
             '*'
         )->addFieldToFilter(
             'customer_id',
-            $this->_customerSession->getCustomer()->getId()
+            $this->_customerSession->getCustomerId()
         )->addFieldToFilter(
             'status',
             array('in' => $this->_orderConfig->getVisibleOnFrontStatuses())
diff --git a/app/code/Magento/Sales/Block/Order/Recent.php b/app/code/Magento/Sales/Block/Order/Recent.php
index 8e5b596f142..468d1f7e43e 100644
--- a/app/code/Magento/Sales/Block/Order/Recent.php
+++ b/app/code/Magento/Sales/Block/Order/Recent.php
@@ -88,7 +88,7 @@ class Recent extends \Magento\Framework\View\Element\Template
             'left'
         )->addAttributeToFilter(
             'customer_id',
-            $this->_customerSession->getCustomer()->getId()
+            $this->_customerSession->getCustomerId()
         )->addAttributeToFilter(
             'status',
             array('in' => $this->_orderConfig->getVisibleOnFrontStatuses())
diff --git a/app/code/Magento/Sales/etc/module.xml b/app/code/Magento/Sales/etc/module.xml
index 80e5a3b4a6f..ac213f93832 100644
--- a/app/code/Magento/Sales/etc/module.xml
+++ b/app/code/Magento/Sales/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Sales" version="1.6.0.12" active="true">
+    <module name="Magento_Sales" schema_version="1.6.0.12" active="true">
         <sequence>
             <module name="Magento_Rule"/>
             <module name="Magento_Catalog"/>
diff --git a/app/code/Magento/SalesRule/etc/module.xml b/app/code/Magento/SalesRule/etc/module.xml
index 9473ffe728e..0d241d2a8da 100644
--- a/app/code/Magento/SalesRule/etc/module.xml
+++ b/app/code/Magento/SalesRule/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_SalesRule" version="1.6.0.4" active="true">
+    <module name="Magento_SalesRule" schema_version="1.6.0.4" active="true">
         <sequence>
             <module name="Magento_Rule"/>
             <module name="Magento_Catalog"/>
diff --git a/app/code/Magento/Sendfriend/etc/module.xml b/app/code/Magento/Sendfriend/etc/module.xml
index 677d686992a..c2ab8496b67 100644
--- a/app/code/Magento/Sendfriend/etc/module.xml
+++ b/app/code/Magento/Sendfriend/etc/module.xml
@@ -25,7 +25,7 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Sendfriend" version="1.6.0.0" active="true">
+    <module name="Magento_Sendfriend" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/Shipping/etc/module.xml b/app/code/Magento/Shipping/etc/module.xml
index 34d73231ab3..e187b74e6aa 100644
--- a/app/code/Magento/Shipping/etc/module.xml
+++ b/app/code/Magento/Shipping/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Shipping" version="1.6.0.0" active="true">
+    <module name="Magento_Shipping" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Sitemap/etc/module.xml b/app/code/Magento/Sitemap/etc/module.xml
index 6799e965400..e181bcab0dc 100644
--- a/app/code/Magento/Sitemap/etc/module.xml
+++ b/app/code/Magento/Sitemap/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Sitemap" version="1.6.0.0" active="true">
+    <module name="Magento_Sitemap" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
         </sequence>
diff --git a/app/code/Magento/Store/etc/module.xml b/app/code/Magento/Store/etc/module.xml
index 157da61d7c1..e5b8467b5b2 100644
--- a/app/code/Magento/Store/etc/module.xml
+++ b/app/code/Magento/Store/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Store" version="2.0.0.0" active="true">
+    <module name="Magento_Store" schema_version="2.0.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
         </sequence>
diff --git a/app/code/Magento/Tax/Model/Calculation.php b/app/code/Magento/Tax/Model/Calculation.php
index 8570082ea31..8e079068752 100644
--- a/app/code/Magento/Tax/Model/Calculation.php
+++ b/app/code/Magento/Tax/Model/Calculation.php
@@ -387,7 +387,14 @@ class Calculation extends \Magento\Framework\Model\AbstractModel
      */
     protected function _getRequestCacheKey($request)
     {
-        $key = $request->getStore() ? $request->getStore()->getId() . '|' : '';
+        $store = $request->getStore();
+        $key = '';
+        if ($store instanceof \Magento\Store\Model\Store) {
+            $key = $store->getId() . '|';
+        } elseif (is_numeric($store)) {
+            $key = $store . '|';
+        }
+
         $key .= $request->getProductClassId() . '|'
             . $request->getCustomerClassId() . '|'
             . $request->getCountryId() . '|'
@@ -483,8 +490,8 @@ class Calculation extends \Magento\Framework\Model\AbstractModel
      *  customer_class_id (->getCustomerClassId())
      *  store (->getStore())
      *
-     * @param   null|bool|\Magento\Framework\Object $shippingAddress
-     * @param   null|bool||\Magento\Framework\Object $billingAddress
+     * @param   null|bool|\Magento\Framework\Object|\Magento\Customer\Service\V1\Data\Address $shippingAddress
+     * @param   null|bool|\Magento\Framework\Object|\Magento\Customer\Service\V1\Data\Address $billingAddress
      * @param   null|int $customerTaxClass
      * @param   null|int|\Magento\Store\Model\Store $store
      * @return  \Magento\Framework\Object
@@ -577,7 +584,7 @@ class Calculation extends \Magento\Framework\Model\AbstractModel
 
         if (is_null($customerTaxClass) && $customerData->getId()) {
             $customerTaxClass = $this->_groupService->getGroup($customerData->getGroupId())->getTaxClassId();
-        } elseif ($customerTaxClass === false || !$customerData->getId()) {
+        } elseif ($customerTaxClass === false && !$customerData->getId()) {
             $customerTaxClass = $this->_groupService->getGroup(GroupServiceInterface::NOT_LOGGED_IN_ID)->getTaxClassId();
         }
 
diff --git a/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php b/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php
new file mode 100644
index 00000000000..4f2c538cad5
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/Rate/Converter.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation\Rate;
+
+use Magento\Tax\Model\Calculation\Rate as TaxRateModel;
+use Magento\Tax\Model\Calculation\RateFactory as TaxRateModelFactory;
+use Magento\Tax\Service\V1\Data\TaxRate as TaxRateDataObject;
+use Magento\Tax\Service\V1\Data\TaxRateBuilder as TaxRateDataObjectBuilder;
+use Magento\Tax\Service\V1\Data\ZipRangeBuilder as ZipRangeDataObjectBuilder;
+
+/**
+ * Tax Rate Model converter.
+ *
+ * Converts a Tax Rate Model to a Data Object or vice versa.
+ */
+class Converter
+{
+    /**
+     * @var TaxRateDataObjectBuilder
+     */
+    protected $taxRateDataObjectBuilder;
+
+    /**
+     * @var TaxRateModelFactory
+     */
+    protected $taxRateModelFactory;
+
+    /**
+     * @var ZipRangeDataObjectBuilder
+     */
+    protected $zipRangeDataObjectBuilder;
+
+    /**
+     * @param TaxRateDataObjectBuilder $taxRateDataObjectBuilder
+     * @param TaxRateModelFactory $taxRateModelFactory
+     * @param ZipRangeDataObjectBuilder $zipRangeDataObjectBuilder
+     */
+    public function __construct(
+        TaxRateDataObjectBuilder $taxRateDataObjectBuilder,
+        TaxRateModelFactory $taxRateModelFactory,
+        ZipRangeDataObjectBuilder $zipRangeDataObjectBuilder
+    ) {
+        $this->taxRateDataObjectBuilder = $taxRateDataObjectBuilder;
+        $this->taxRateModelFactory = $taxRateModelFactory;
+        $this->zipRangeDataObjectBuilder = $zipRangeDataObjectBuilder;
+    }
+
+    /**
+     * Convert a rate model to a TaxRate data object
+     *
+     * @param TaxRateModel $rateModel
+     * @return TaxRateDataObject
+     */
+    public function createTaxRateDataObjectFromModel(TaxRateModel $rateModel)
+    {
+        $this->taxRateDataObjectBuilder->populateWithArray([]);
+        if ($rateModel->getId()) {
+            $this->taxRateDataObjectBuilder->setId($rateModel->getId());
+        }
+        if ($rateModel->getTaxCountryId()) {
+            $this->taxRateDataObjectBuilder->setCountryId($rateModel->getTaxCountryId());
+        }
+        if ($rateModel->getTaxRegionId()) {
+            $this->taxRateDataObjectBuilder->setRegionId($rateModel->getTaxRegionId());
+        }
+        if ($rateModel->getTaxPostcode()) {
+            $this->taxRateDataObjectBuilder->setPostcode($rateModel->getTaxPostcode());
+        }
+        if ($rateModel->getCode()) {
+            $this->taxRateDataObjectBuilder->setCode($rateModel->getCode());
+        }
+        if ($rateModel->getRate()) {
+            $this->taxRateDataObjectBuilder->setPercentageRate($rateModel->getRate());
+        }
+        if ($rateModel->getZipIsRange()) {
+            $zipRange = $this->zipRangeDataObjectBuilder->populateWithArray([])
+                ->setFrom($rateModel->getZipFrom())
+                ->setTo($rateModel->getZipTo())
+                ->create();
+            $this->taxRateDataObjectBuilder->setZipRange($zipRange);
+        }
+        return $this->taxRateDataObjectBuilder->create();
+    }
+
+    /**
+     * Convert a TaxRate data object to rate model
+     *
+     * @param TaxRateDataObject $taxRate
+     * @return TaxRateModel
+     */
+    public function createTaxRateModel(TaxRateDataObject $taxRate)
+    {
+        $rateModel = $this->taxRateModelFactory->create();
+        $rateId = $taxRate->getId();
+        if ($rateId) {
+            $rateModel->setId($rateId);
+        }
+        $rateModel->setTaxCountryId($taxRate->getCountryId());
+        $rateModel->setTaxRegionId($taxRate->getRegionId());
+        $rateModel->setRate($taxRate->getPercentageRate());
+        $rateModel->setCode($taxRate->getCode());
+        $rateModel->setTaxPostcode($taxRate->getPostCode());
+        $zipRange = $taxRate->getZipRange();
+        if ($zipRange) {
+            $zipFrom = $zipRange->getFrom();
+            $zipTo = $zipRange->getTo();
+            if (!empty($zipFrom) || !empty($zipTo)) {
+                $rateModel->setZipIsRange(1);
+            }
+            $rateModel->setZipFrom($zipFrom);
+            $rateModel->setZipTo($zipTo);
+        }
+        return $rateModel;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/RateRegistry.php b/app/code/Magento/Tax/Model/Calculation/RateRegistry.php
new file mode 100644
index 00000000000..79dcf14f1ba
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/RateRegistry.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation\RateFactory as TaxRateModelFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Tax\Model\Calculation\Rate as TaxRateModel;
+
+class RateRegistry
+{
+    /**
+     * Tax rate model factory
+     *
+     * @var  TaxRateModelFactory
+     */
+    private $taxRateModelFactory;
+
+    /**
+     * Tax rate models
+     *
+     * @var TaxRateModel[]
+     */
+    private $taxRateRegistryById = [];
+
+    /**
+     * Constructor
+     *
+     * @param TaxRateModelFactory $taxModelRateFactory
+     */
+    public function __construct(
+        TaxRateModelFactory $taxModelRateFactory
+    ) {
+        $this->taxRateModelFactory = $taxModelRateFactory;
+    }
+
+    /**
+     * Register TaxRate Model to registry
+     *
+     * @param TaxRateModel $taxRateModel
+     * @return void
+     */
+    public function registerTaxRate(TaxRateModel $taxRateModel)
+    {
+        $this->taxRateRegistryById[$taxRateModel->getId()] = $taxRateModel;
+    }
+
+    /**
+     * Retrieve TaxRate Model from registry given an id
+     *
+     * @param int $taxRateId
+     * @return TaxRateModel
+     * @throws NoSuchEntityException
+     */
+    public function retrieveTaxRate($taxRateId)
+    {
+        if (isset($this->taxRateRegistryById[$taxRateId])) {
+            return $this->taxRateRegistryById[$taxRateId];
+        }
+        /** @var TaxRateModel $taxRateModel */
+        $taxRateModel = $this->taxRateModelFactory->create()->load($taxRateId);
+        if (!$taxRateModel->getId()) {
+            // tax rate does not exist
+            throw NoSuchEntityException::singleField('taxRateId', $taxRateId);
+        }
+        $this->taxRateRegistryById[$taxRateModel->getId()] = $taxRateModel;
+        return $taxRateModel;
+    }
+
+    /**
+     * Remove an instance of the TaxRate Model from the registry
+     *
+     * @param int $taxRateId
+     * @return void
+     */
+    public function removeTaxRate($taxRateId)
+    {
+        unset($this->taxRateRegistryById[$taxRateId]);
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/TaxRuleConverter.php b/app/code/Magento/Tax/Model/Calculation/TaxRuleConverter.php
new file mode 100644
index 00000000000..d574a346c3c
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/TaxRuleConverter.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation\Rule as TaxRuleModel;
+use Magento\Tax\Model\Calculation\RuleFactory as TaxRuleModelFactory;
+use Magento\Tax\Service\V1\Data\TaxRule as TaxRuleDataObject;
+use Magento\Tax\Service\V1\Data\TaxRuleBuilder as TaxRuleDataObjectBuilder;
+
+/**
+ * Tax Rule Model converter.
+ *
+ * Converts a Tax Rule Model to a Data Object or vice versa.
+ */
+class TaxRuleConverter
+{
+    /**
+     * @var TaxRuleDataObjectBuilder
+     */
+    protected $taxRuleDataObjectBuilder;
+
+    /**
+     * @var TaxRuleModelFactory
+     */
+    protected $taxRuleModelFactory;
+
+    /**
+     * @param TaxRuleDataObjectBuilder $taxRuleDataObjectBuilder
+     * @param TaxRuleModelFactory $taxRuleModelFactory
+     */
+    public function __construct(
+        TaxRuleDataObjectBuilder $taxRuleDataObjectBuilder,
+        TaxRuleModelFactory $taxRuleModelFactory
+    ) {
+        $this->taxRuleDataObjectBuilder = $taxRuleDataObjectBuilder;
+        $this->taxRuleModelFactory = $taxRuleModelFactory;
+    }
+
+    /**
+     * Convert a rate model to a TaxRate data object
+     *
+     * @param TaxRuleModel $ruleModel
+     * @return TaxRuleDataObject
+     */
+    public function createTaxRuleDataObjectFromModel(TaxRuleModel $ruleModel)
+    {
+        if (!is_null($ruleModel->getId())) {
+            $this->taxRuleDataObjectBuilder->setId($ruleModel->getId());
+        }
+        if (!is_null($ruleModel->getCode())) {
+            $this->taxRuleDataObjectBuilder->setCode($ruleModel->getCode());
+        }
+        if (!is_null($ruleModel->getCustomerTaxClasses())) {
+            $this->taxRuleDataObjectBuilder->setCustomerTaxClassIds(array_unique($ruleModel->getCustomerTaxClasses()));
+        }
+        if (!is_null($ruleModel->getProductTaxClasses())) {
+            $this->taxRuleDataObjectBuilder->setProductTaxClassIds(array_unique($ruleModel->getProductTaxClasses()));
+        }
+        if (!is_null($ruleModel->getRates())) {
+            $this->taxRuleDataObjectBuilder->setTaxRateIds(array_unique($ruleModel->getRates()));
+        }
+        if (!is_null($ruleModel->getPriority())) {
+            $this->taxRuleDataObjectBuilder->setPriority($ruleModel->getPriority());
+        }
+        if (!is_null($ruleModel->getPosition())) {
+            $this->taxRuleDataObjectBuilder->setSortOrder($ruleModel->getPosition());
+        }
+        return $this->taxRuleDataObjectBuilder->create();
+    }
+
+    /**
+     * Convert a tax rule data object to tax rule model
+     *
+     * @param TaxRuleDataObject $taxRule
+     * @return TaxRuleModel
+     */
+    public function createTaxRuleModel(TaxRuleDataObject $taxRuleDataObject)
+    {
+        $taxRuleModel = $this->taxRuleModelFactory->create();
+        $ruleId = $taxRuleDataObject->getId();
+        if ($ruleId) {
+            $taxRuleModel->setId($ruleId);
+        }
+        $taxRuleModel->setTaxCustomerClass($taxRuleDataObject->getCustomerTaxClassIds());
+        $taxRuleModel->setTaxProductClass($taxRuleDataObject->getProductTaxClassIds());
+        $taxRuleModel->setTaxRate($taxRuleDataObject->getTaxRateIds());
+        $taxRuleModel->setCode($taxRuleDataObject->getCode());
+        $taxRuleModel->setPriority($taxRuleDataObject->getPriority());
+        $taxRuleModel->setPosition($taxRuleDataObject->getSortOrder());
+        return $taxRuleModel;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Calculation/TaxRuleRegistry.php b/app/code/Magento/Tax/Model/Calculation/TaxRuleRegistry.php
new file mode 100644
index 00000000000..610e04b38d3
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Calculation/TaxRuleRegistry.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Tax\Model\Calculation\RuleFactory as TaxRuleModelFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Tax\Model\Calculation\Rule as TaxRuleModel;
+
+class TaxRuleRegistry
+{
+    /** @var  TaxRuleModelFactory */
+    private $taxRuleModelFactory;
+
+    /**
+     * @var array taxRuleId => TaxRuleModel
+     */
+    private $registry = [];
+
+    /**
+     * Constructor
+     *
+     * @param TaxRuleModelFactory $taxRuleModelFactory
+     */
+    public function __construct(
+        TaxRuleModelFactory $taxRuleModelFactory
+    ) {
+        $this->taxRuleModelFactory = $taxRuleModelFactory;
+    }
+
+    /**
+     * Registers TaxRule Model to registry
+     *
+     * @param TaxRuleModel $taxRuleModel
+     * @return void
+     */
+    public function registerTaxRule(TaxRuleModel $taxRuleModel)
+    {
+        $this->registry[$taxRuleModel->getId()] = $taxRuleModel;
+    }
+
+    /**
+     * Retrieve TaxRule Model from registry given an id
+     *
+     * @param int $taxRuleId
+     * @return TaxRuleModel
+     * @throws NoSuchEntityException
+     */
+    public function retrieveTaxRule($taxRuleId)
+    {
+        if (isset($this->registry[$taxRuleId])) {
+            return $this->registry[$taxRuleId];
+        }
+        $taxRuleModel = $this->taxRuleModelFactory->create()->load($taxRuleId);
+        if (!$taxRuleModel->getId()) {
+            // tax rule does not exist
+            throw NoSuchEntityException::singleField('taxRuleId', $taxRuleId);
+        }
+        $this->registry[$taxRuleModel->getId()] = $taxRuleModel;
+        return $taxRuleModel;
+    }
+
+    /**
+     * Remove an instance of the TaxRule Model from the registry
+     *
+     * @param int $taxRuleId
+     * @return void
+     */
+    public function removeTaxRule($taxRuleId)
+    {
+        unset($this->registry[$taxRuleId]);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
new file mode 100644
index 00000000000..5d1d4fd7a24
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+class QuoteDetails extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_BILLING_ADDRESS = 'billing_address';
+
+    const KEY_SHIPPING_ADDRESS = 'shipping_address';
+
+    const KEY_CUSTOMER_TAX_CLASS_ID = 'customer_tax_class_id';
+
+    const KEY_ITEMS = 'items';
+    /**#@-*/
+
+    /**
+     * Get customer billing address
+     *
+     * @return \Magento\Customer\Service\V1\Data\Address|null
+     */
+    public function getBillingAddress()
+    {
+        return $this->_get(self::KEY_BILLING_ADDRESS);
+    }
+
+    /**
+     * Get customer shipping address
+     *
+     * @return \Magento\Customer\Service\V1\Data\Address|null
+     */
+    public function getShippingAddress()
+    {
+        return $this->_get(self::KEY_SHIPPING_ADDRESS);
+    }
+
+    /**
+     * Get customer tax class id
+     *
+     * @return int|null
+     */
+    public function getCustomerTaxClassId()
+    {
+        return $this->_get(self::KEY_CUSTOMER_TAX_CLASS_ID);
+    }
+
+    /**
+     * Get quote items
+     *
+     * @return \Magento\Tax\Service\V1\Data\QuoteDetails\Item[]|null
+     */
+    public function getItems()
+    {
+        return $this->_get(self::KEY_ITEMS);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
new file mode 100644
index 00000000000..7be400b1738
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/Item.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data\QuoteDetails;
+
+class Item extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_CODE = 'code';
+
+    const KEY_TYPE = 'type';
+
+    const KEY_TAX_CLASS_ID = 'tax_class_id';
+
+    const KEY_UNIT_PRICE = 'unit_price';
+
+    const KEY_QUANTITY = 'quantity';
+
+    const KEY_TAX_INCLUDED = 'tax_included';
+
+    const KEY_SHORT_DESCRIPTION = 'short_description';
+
+    const KEY_DISCOUNT_AMOUNT = 'discount_amount';
+
+    const KEY_PARENT_CODE = 'parent_code';
+    /**#@-*/
+
+    /**
+     * Get code (sku or shipping code)
+     *
+     * @return string|null
+     */
+    public function getCode()
+    {
+        return $this->_get(self::KEY_CODE);
+    }
+
+    /**
+     * Get type (e.g., shipping, product, wee, gift wrapping, etc.)
+     *
+     * @return string|null
+     */
+    public function getType()
+    {
+        return $this->_get(self::KEY_TYPE);
+    }
+
+    /**
+     * Get tax class id
+     *
+     * @return int
+     */
+    public function getTaxClassId()
+    {
+        return $this->_get(self::KEY_TAX_CLASS_ID);
+    }
+
+    /**
+     * Get unit price
+     *
+     * @return float
+     */
+    public function getUnitPrice()
+    {
+        return $this->_get(self::KEY_UNIT_PRICE);
+    }
+
+    /**
+     * Get quantity
+     *
+     * @return float
+     */
+    public function getQuantity()
+    {
+        return $this->_get(self::KEY_QUANTITY);
+    }
+
+    /**
+     * Get indicate that if the tax is included in the unit price and row total
+     *
+     * @return bool
+     */
+    public function getTaxIncluded()
+    {
+        return $this->_get(self::KEY_TAX_INCLUDED);
+    }
+
+    /**
+     * Get short description
+     *
+     * @return string|null
+     */
+    public function getShortDescription()
+    {
+        return $this->_get(self::KEY_SHORT_DESCRIPTION);
+    }
+
+    /**
+     * Get discount amount
+     *
+     * @return float
+     */
+    public function getDiscountAmount()
+    {
+        return $this->_get(self::KEY_DISCOUNT_AMOUNT);
+    }
+
+    /**
+     * Get parent code if this item is a child, null if this is a top level item.
+     *
+     * @return string|null
+     */
+    public function getParentCode()
+    {
+        return $this->_get(self::KEY_PARENT_CODE);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
new file mode 100644
index 00000000000..0b94e9246af
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetails/ItemBuilder.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data\QuoteDetails;
+
+/**
+ * Builder for the Item Service Data Object
+ *
+ * @method Item create()
+ */
+class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Set code (sku or shipping code)
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setCode($code)
+    {
+        return $this->_set(Item::KEY_CODE, $code);
+    }
+
+    /**
+     * Set type (e.g., shipping, product, wee, gift wrapping, etc.)
+     *
+     * @param string $type
+     * @return $this
+     */
+    public function setType($type)
+    {
+        return $this->_set(Item::KEY_TYPE, $type);
+    }
+
+    /**
+     * Set tax class id
+     *
+     * @param int $taxClassId
+     * @return $this
+     */
+    public function setTaxClassId($taxClassId)
+    {
+        return $this->_set(Item::KEY_TAX_CLASS_ID, $taxClassId);
+    }
+
+    /**
+     * Set unit price
+     *
+     * @param float $unitPrice
+     * @return $this
+     */
+    public function setUnitPrice($unitPrice)
+    {
+        return $this->_set(Item::KEY_UNIT_PRICE, $unitPrice);
+    }
+
+    /**
+     * Set quantity
+     *
+     * @param float $quantity
+     * @return $this
+     */
+    public function setQuantity($quantity)
+    {
+        return $this->_set(Item::KEY_QUANTITY, $quantity);
+    }
+
+    /**
+     * Set indicate that if the tax is included in the unit price and row total
+     *
+     * @param bool $taxIncluded
+     * @return $this
+     */
+    public function setTaxIncluded($taxIncluded)
+    {
+        return $this->_set(Item::KEY_TAX_INCLUDED, $taxIncluded);
+    }
+
+    /**
+     * Set short description
+     *
+     * @param string $shortDescription
+     * @return $this
+     */
+    public function setShortDescription($shortDescription)
+    {
+        return $this->_set(Item::KEY_SHORT_DESCRIPTION, $shortDescription);
+    }
+
+    /**
+     * Set discount amount
+     *
+     * @param float $amount
+     * @return $this
+     */
+    public function setDiscountAmount($amount)
+    {
+        return $this->_set(Item::KEY_DISCOUNT_AMOUNT, $amount);
+    }
+
+    /**
+     * Set parent code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setParentCode($code)
+    {
+        return $this->_set(Item::KEY_PARENT_CODE, $code);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php b/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
new file mode 100644
index 00000000000..1b38c8bc78a
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/QuoteDetailsBuilder.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+/**
+ * QuoteDetailsBuilder
+ *
+ * @method QuoteDetails create()
+ */
+class QuoteDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * QuoteDetails item builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder
+     */
+    protected $itemBuilder;
+
+    /**
+     * Initialize dependencies.
+     *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $itemBuilder
+     * @param \Magento\Customer\Service\V1\Data\AddressBuilder $addressBuilder
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder $itemBuilder,
+        \Magento\Customer\Service\V1\Data\AddressBuilder $addressBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->itemBuilder = $itemBuilder;
+        $this->addressBuilder = $addressBuilder;
+    }
+
+    /**
+     * Set customer billing address
+     *
+     * @param \Magento\Customer\Service\V1\Data\Address $address
+     * @return $this
+     */
+    public function setBillingAddress($address)
+    {
+        return $this->_set(QuoteDetails::KEY_BILLING_ADDRESS, $address);
+    }
+
+    /**
+     * Set customer shipping address
+     *
+     * @param \Magento\Customer\Service\V1\Data\Address $address
+     * @return $this
+     */
+    public function setShippingAddress($address)
+    {
+        return $this->_set(QuoteDetails::KEY_SHIPPING_ADDRESS, $address);
+    }
+
+    /**
+     * Set customer tax class id
+     *
+     * @param int $taxClassId
+     * @return $this
+     */
+    public function setCustomerTaxClassId($taxClassId)
+    {
+        return $this->_set(QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID, $taxClassId);
+    }
+
+    /**
+     * Set quote items
+     *
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetails\Item[]|null $items
+     * @return $this
+     */
+    public function setItems($items)
+    {
+        return $this->_set(QuoteDetails::KEY_ITEMS, $items);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        if (array_key_exists(QuoteDetails::KEY_BILLING_ADDRESS, $data)) {
+            $data[QuoteDetails::KEY_BILLING_ADDRESS] = $this->addressBuilder->populateWithArray(
+                $data[QuoteDetails::KEY_BILLING_ADDRESS]
+            )->create();
+        }
+        if (array_key_exists(QuoteDetails::KEY_SHIPPING_ADDRESS, $data)) {
+            $data[QuoteDetails::KEY_SHIPPING_ADDRESS] = $this->addressBuilder->populateWithArray(
+                $data[QuoteDetails::KEY_SHIPPING_ADDRESS]
+            )->create();
+        }
+        if (array_key_exists(QuoteDetails::KEY_ITEMS, $data)) {
+            $items = [];
+            foreach ($data[QuoteDetails::KEY_ITEMS] as $itemArray) {
+                $items[] = $this->itemBuilder->populateWithArray($itemArray)->create();
+            }
+            $data[QuoteDetails::KEY_ITEMS] = $items;
+        }
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails.php
new file mode 100644
index 00000000000..5f7423b3991
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+class TaxDetails extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_SUBTOTAL = 'subtotal';
+
+    const KEY_TAX_AMOUNT = 'tax_amount';
+
+    const KEY_DISCOUNT_AMOUNT = 'discount_amount';
+
+    const KEY_APPLIED_TAXES = 'applied_taxes';
+
+    const KEY_ITEMS = 'items';
+
+    /**#@-*/
+
+    /**
+     * Get subtotal
+     *
+     * @return float
+     */
+    public function getSubtotal()
+    {
+        return $this->_get(self::KEY_SUBTOTAL);
+    }
+
+    /**
+     * Get tax amount
+     *
+     * @return float
+     */
+    public function getTaxAmount()
+    {
+        return $this->_get(self::KEY_TAX_AMOUNT);
+    }
+
+    /**
+     * Get discount amount
+     *
+     * @return float
+     */
+    public function getDiscountAmount()
+    {
+        return $this->_get(self::KEY_DISCOUNT_AMOUNT);
+    }
+
+    /**
+     * Get applied taxes
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] | null
+     */
+    public function getAppliedTaxes()
+    {
+        return $this->_get(self::KEY_APPLIED_TAXES);
+    }
+
+    /**
+     * Get TaxDetails items
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\Item[] | null
+     */
+    public function getItems()
+    {
+        return $this->_get(self::KEY_ITEMS);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/SchemaLocator.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTax.php
similarity index 53%
rename from lib/internal/Magento/Framework/Locale/Hierarchy/Config/SchemaLocator.php
rename to app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTax.php
index 85d8157ef8e..ee9882f101a 100644
--- a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/SchemaLocator.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTax.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Locale hierarchy configuration schema locator
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -23,49 +21,59 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Framework\Locale\Hierarchy\Config;
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
 
-class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface
+class AppliedTax extends \Magento\Framework\Service\Data\AbstractObject
 {
-    /**
-     * Path to corresponding XSD file with validation rules for merged config
-     *
-     * @var string
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
      */
-    protected $_schema = null;
+    const KEY_TAX_RATE_KEY = 'tax_rate_key';
+
+    const KEY_PERCENT = 'percent';
+
+    const KEY_AMOUNT = 'amount';
+
+    const KEY_RATES = 'rates';
+    /**#@-*/
 
     /**
-     * Path to corresponding XSD file with validation rules for separate config files
+     * Get tax rate key
      *
-     * @var string
+     * @return string|null
      */
-    protected $_perFileSchema = null;
+    public function getTaxRateKey()
+    {
+        return $this->_get(self::KEY_TAX_RATE_KEY);
+    }
 
     /**
-     * @param \Magento\Framework\Module\Dir\Reader $moduleReader
+     * Get percent
+     *
+     * @return float
      */
-    public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader)
+    public function getPercent()
     {
-        $this->_schema = $moduleReader->getModuleDir('etc', 'Magento_Core') . '/' . 'locale.xsd';
+        return $this->_get(self::KEY_PERCENT);
     }
 
     /**
-     * Get path to merged config schema
+     * Get amount
      *
-     * @return string|null
+     * @return float
      */
-    public function getSchema()
+    public function getAmount()
     {
-        return $this->_schema;
+        return $this->_get(self::KEY_AMOUNT);
     }
 
     /**
-     * Get path to pre file validation schema
+     * Get rates
      *
-     * @return string|null
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxRate[]|null
      */
-    public function getPerFileSchema()
+    public function getRates()
     {
-        return $this->_perFileSchema;
+        return $this->_get(self::KEY_RATES);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilder.php
new file mode 100644
index 00000000000..7298e045b64
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilder.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+/**
+ * Builder for the AppliedTax Service Data Object
+ *
+ * @method AppliedTax create()
+ */
+class AppliedTaxBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * AppliedTaxRate builder
+     *
+     * @var AppliedTaxRateBuilder
+     */
+    protected $appliedTaxRateBuilder;
+
+    /**
+     * Initialize dependencies.
+     *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param AppliedTaxRateBuilder $appliedTaxRateBuilder
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        AppliedTaxRateBuilder $appliedTaxRateBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->appliedTaxRateBuilder = $appliedTaxRateBuilder;
+    }
+
+    /**
+     * Set tax rate key
+     *
+     * @param string $key
+     * @return $this
+     */
+    public function setTaxRateKey($key)
+    {
+        return $this->_set(AppliedTax::KEY_TAX_RATE_KEY, $key);
+    }
+
+    /**
+     * Set percent
+     *
+     * @param float $percent
+     * @return $this
+     */
+    public function setPercent($percent)
+    {
+        return $this->_set(AppliedTax::KEY_PERCENT, $percent);
+    }
+
+    /**
+     * Set amount
+     *
+     * @param float $amount
+     * @return $this
+     */
+    public function setAmount($amount)
+    {
+        return $this->_set(AppliedTax::KEY_AMOUNT, $amount);
+    }
+
+    /**
+     * Set rates
+     *
+     * @param AppliedTaxRate[] $rates
+     * @return $this
+     */
+    public function setRates($rates)
+    {
+        return $this->_set(AppliedTax::KEY_RATES, $rates);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        if (array_key_exists(AppliedTax::KEY_RATES, $data)) {
+            $rates = [];
+            foreach ($data[AppliedTax::KEY_RATES] as $rateArray) {
+                $rates[] = $this->appliedTaxRateBuilder->populateWithArray($rateArray)->create();
+            }
+            $data[AppliedTax::KEY_RATES] = $rates;
+        }
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRate.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRate.php
new file mode 100644
index 00000000000..51a25f8a9d4
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRate.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+class AppliedTaxRate extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_CODE = 'code';
+
+    const KEY_TITLE = 'title';
+
+    const KEY_PERCENT = 'percent';
+    /**#@-*/
+
+    /**
+     * Get code
+     *
+     * @return string|null
+     */
+    public function getCode()
+    {
+        return $this->_get(self::KEY_CODE);
+    }
+
+    /**
+     * Get Title
+     *
+     * @return string|null
+     */
+    public function getTitle()
+    {
+        return $this->_get(self::KEY_TITLE);
+    }
+
+    /**
+     * Get Tax Percent
+     *
+     * @return float|null
+     */
+    public function getPercent()
+    {
+        return $this->_get(self::KEY_PERCENT);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/SearchResultsBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRateBuilder.php
similarity index 57%
rename from app/code/Magento/Catalog/Service/V1/Data/SearchResultsBuilder.php
rename to app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRateBuilder.php
index 9335515de92..99a5f352c95 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/SearchResultsBuilder.php
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxRateBuilder.php
@@ -21,48 +21,45 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-
-namespace Magento\Catalog\Service\V1\Data;
-
-use Magento\Framework\Service\V1\Data\SearchCriteria;
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
 
 /**
- * Builder for the SearchResults Service Data Object
+ * Builder for the AppliedTaxRate Service Data Object
  *
- * @method SearchResults create()
+ * @method AppliedTaxRate create()
  */
-class SearchResultsBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+class AppliedTaxRateBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
 {
     /**
-     * Set search criteria
+     * Set code
      *
-     * @param SearchCriteria $searchCriteria
+     * @param string $code
      * @return $this
      */
-    public function setSearchCriteria(SearchCriteria $searchCriteria)
+    public function setCode($code)
     {
-        return $this->_set('search_criteria', $searchCriteria);
+        return $this->_set(AppliedTaxRate::KEY_CODE, $code);
     }
 
     /**
-     * Set total count
+     * Set title
      *
-     * @param int $totalCount
+     * @param string $title
      * @return $this
      */
-    public function setTotalCount($totalCount)
+    public function setTitle($title)
     {
-        return $this->_set('total_count', $totalCount);
+        return $this->_set(AppliedTaxRate::KEY_TITLE, $title);
     }
 
     /**
-     * Set items
+     * Set tax percent
      *
-     * @param \Magento\Catalog\Service\V1\Data\Product[] $items
+     * @param float $percent
      * @return $this
      */
-    public function setItems($items)
+    public function setPercent($percent)
     {
-        return $this->_set('items', $items);
+        return $this->_set(AppliedTaxRate::KEY_PERCENT, $percent);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
new file mode 100644
index 00000000000..01fe828d14f
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/Item.php
@@ -0,0 +1,164 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+class Item extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_CODE = 'code';
+
+    const KEY_TYPE = 'type';
+
+    const KEY_TAX_PERCENT = 'tax_percent';
+
+    const KEY_PRICE = 'price';
+
+    const KEY_PRICE_INCL_TAX = 'price_incl_tax';
+
+    const KEY_ROW_TOTAL = 'row_total';
+
+    const KEY_ROW_TAX = 'row_tax';
+
+    const KEY_TAXABLE_AMOUNT = 'taxable_amount';
+
+    const KEY_DISCOUNT_AMOUNT = 'discount_amount';
+
+    const KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount';
+
+    const KEY_APPLIED_TAXES = 'applied_taxes';
+    /**#@-*/
+
+    /**
+     * Get code (sku or shipping code)
+     *
+     * @return string|null
+     */
+    public function getCode()
+    {
+        return $this->_get(self::KEY_CODE);
+    }
+
+    /**
+     * Get type (shipping, product, weee, gift wrapping, etc
+     *
+     * @return string|null
+     */
+    public function getType()
+    {
+        return $this->_get(self::KEY_TYPE);
+    }
+
+    /**
+     * Get tax_percent
+     *
+     * @return float
+     */
+    public function getTaxPercent()
+    {
+        return $this->_get(self::KEY_TAX_PERCENT);
+    }
+
+    /**
+     * Get price
+     *
+     * @return float
+     */
+    public function getPrice()
+    {
+        return $this->_get(self::KEY_PRICE);
+    }
+
+    /**
+     * Get price including tax
+     *
+     * @return float
+     */
+    public function getPriceInclTax()
+    {
+        return $this->_get(self::KEY_PRICE_INCL_TAX);
+    }
+
+    /**
+     * Get row total
+     *
+     * @return float
+     */
+    public function getRowTotal()
+    {
+        return $this->_get(self::KEY_ROW_TOTAL);
+    }
+
+    /**
+     * Get row tax amount
+     *
+     * @return float
+     */
+    public function getRowTax()
+    {
+        return $this->_get(self::KEY_ROW_TAX);
+    }
+
+    /**
+     * Get taxable amount
+     *
+     * @return float
+     */
+    public function getTaxableAmount()
+    {
+        return $this->_get(self::KEY_TAXABLE_AMOUNT);
+    }
+
+    /**
+     * Get discount amount
+     *
+     * @return float
+     */
+    public function getDiscountAmount()
+    {
+        return $this->_get(self::KEY_DISCOUNT_AMOUNT);
+    }
+
+    /**
+     * Get discount tax compensation amount
+     *
+     * @return float
+     */
+    public function getDiscountTaxCompensationAmount()
+    {
+        return $this->_get(self::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT);
+    }
+
+    /**
+     * Get applied taxes
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] | null
+     */
+    public function getAppliedTaxes()
+    {
+        return $this->_get(self::KEY_APPLIED_TAXES);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
new file mode 100644
index 00000000000..0f036738629
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilder.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+use Magento\Tax\Service\V1\Data\TaxDetails;
+
+/**
+ * Builder for the TaxDetails Item Data Object
+ *
+ * @method Item create()
+ */
+
+class ItemBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Applied Tax data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder
+     */
+    protected $appliedTaxBuilder;
+
+    /**
+     * Initialize dependencies
+     *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param AppliedTaxBuilder $appliedTaxBuilder
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder $appliedTaxBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->appliedTaxBuilder = $appliedTaxBuilder;
+    }
+
+    /**
+     * Set code (sku or shipping code)
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setCode($code)
+    {
+        $this->_set(Item::KEY_CODE, $code);
+        return $this;
+    }
+
+    /**
+     * Set type (shipping, product, weee, gift wrapping, etc.)
+     *
+     * @param string $type
+     * @return $this
+     */
+    public function setType($type)
+    {
+        $this->_set(Item::KEY_TYPE, $type);
+        return $this;
+    }
+
+    /**
+     * Set tax percent
+     *
+     * @param float $taxPercent
+     * @return $this
+     */
+    public function setTaxPercent($taxPercent)
+    {
+        $this->_set(Item::KEY_TAX_PERCENT, $taxPercent);
+        return $this;
+    }
+
+    /**
+     * Set price
+     *
+     * @param float $price
+     * @return $this
+     */
+    public function setPrice($price)
+    {
+        $this->_set(Item::KEY_PRICE, $price);
+        return $this;
+    }
+
+    /**
+     * Set price including tax
+     *
+     * @param float $priceInclTax
+     * @return $this
+     */
+    public function setPriceInclTax($priceInclTax)
+    {
+        $this->_set(Item::KEY_PRICE_INCL_TAX, $priceInclTax);
+        return $this;
+    }
+
+    /**
+     * Set row total
+     *
+     * @param float $rowTotal
+     * @return $this
+     */
+    public function setRowTotal($rowTotal)
+    {
+        $this->_set(Item::KEY_ROW_TOTAL, $rowTotal);
+        return $this;
+    }
+
+    /**
+     * Set tax amount
+     *
+     * @param float $taxAmount
+     * @return $this
+     */
+    public function setRowTax($taxAmount)
+    {
+        $this->_set(Item::KEY_ROW_TAX, $taxAmount);
+        return $this;
+    }
+
+    /**
+     * Set taxable amount
+     *
+     * @param float $taxableAmount
+     * @return $this
+     */
+    public function setTaxableAmount($taxableAmount)
+    {
+        $this->_set(Item::KEY_TAXABLE_AMOUNT, $taxableAmount);
+        return $this;
+    }
+
+    /**
+     * Set discount amount
+     *
+     * @param float $discountAmount
+     * @return $this
+     */
+    public function setDiscountAmount($discountAmount)
+    {
+        $this->_set(Item::KEY_DISCOUNT_AMOUNT, $discountAmount);
+        return $this;
+    }
+
+    /**
+     * Set discount tax compensation amount
+     *
+     * @param float $discountTaxCompensationAmount
+     * @return $this
+     */
+    public function setDiscountTaxCompensationAmount($discountTaxCompensationAmount)
+    {
+        $this->_set(Item::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT, $discountTaxCompensationAmount);
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        $appliedTaxDataObjects = [];
+
+        if (isset($data[Item::KEY_APPLIED_TAXES])) {
+            $appliedTaxes = $data[Item::KEY_APPLIED_TAXES];
+            foreach ($appliedTaxes as $appliedTax) {
+                $appliedTaxDataObjects[] = $this->appliedTaxBuilder->populateWithArray($appliedTax)->create();
+            }
+        }
+
+        $data[Item::KEY_APPLIED_TAXES] = $appliedTaxDataObjects;
+
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxDetailsBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxDetailsBuilder.php
new file mode 100644
index 00000000000..64f0af238f9
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxDetailsBuilder.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+/**
+ * Builder for the TaxDetails Data Object
+ *
+ * @method TaxDetails create()
+ */
+class TaxDetailsBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Applied Tax data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder
+     */
+    protected $appliedTaxBuilder;
+
+    /**
+     * Tax Details Item data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder
+     */
+    protected $taxDetailsItemBuilder;
+
+    /**
+     * Initialize dependencies
+     *
+     * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory
+     * @param TaxDetails\AppliedTaxBuilder $appliedTaxBuilder
+     * @param TaxDetails\ItemBuilder $taxDetailsItemBuilder
+     */
+    public function __construct(
+        \Magento\Framework\Service\Data\ObjectFactory $objectFactory,
+        \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder $appliedTaxBuilder,
+        \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder $taxDetailsItemBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->appliedTaxBuilder = $appliedTaxBuilder;
+        $this->taxDetailsItemBuilder = $taxDetailsItemBuilder;
+    }
+
+    /**
+     * Set subtotal
+     *
+     * @param float $subtotal
+     * @return $this
+     */
+    public function setSubtotal($subtotal)
+    {
+        $this->_set(TaxDetails::KEY_SUBTOTAL, $subtotal);
+        return $this;
+    }
+
+    /**
+     * Set tax amount
+     *
+     * @param float $taxAmount
+     * @return $this
+     */
+    public function setTaxAmount($taxAmount)
+    {
+        $this->_set(TaxDetails::KEY_TAX_AMOUNT, $taxAmount);
+        return $this;
+    }
+
+    /**
+     * Set discount amount
+     *
+     * @param float $discountAmount
+     * @return $this
+     */
+    public function setDiscountAmount($discountAmount)
+    {
+        $this->_set(TaxDetails::KEY_DISCOUNT_AMOUNT, $discountAmount);
+        return $this;
+    }
+
+    /**
+     * Set applied taxes
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] | null $appliedTaxes
+     * @return $this
+     */
+    public function setAppliedTaxes($appliedTaxes)
+    {
+        $this->_set(TaxDetails::KEY_APPLIED_TAXES, $appliedTaxes);
+        return $this;
+    }
+
+    /**
+     * Set Tax Details items
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxDetails\Item[] | null $items
+     * @return $this
+     */
+    public function setItems($items)
+    {
+        $this->_set(TaxDetails::KEY_ITEMS, $items);
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function _setDataValues(array $data)
+    {
+        if (isset($data[TaxDetails::KEY_APPLIED_TAXES])) {
+            $appliedTaxDataObjects = [];
+            $appliedTaxes = $data[TaxDetails::KEY_APPLIED_TAXES];
+            foreach ($appliedTaxes as $appliedTax) {
+                $appliedTaxDataObjects[] = $this->appliedTaxBuilder
+                    ->populateWithArray($appliedTax)->create();
+            }
+            $data[TaxDetails::KEY_APPLIED_TAXES] = $appliedTaxDataObjects;
+        }
+
+        if (isset($data[TaxDetails::KEY_ITEMS])) {
+            $taxDetailItemDataObjects = [];
+            $taxDetailItems = $data[TaxDetails::KEY_ITEMS];
+            foreach ($taxDetailItems as $taxDetailItem) {
+                $taxDetailItemDataObjects[] = $this->taxDetailsItemBuilder
+                    ->populateWithArray($taxDetailItem)->create();
+            }
+            $data[TaxDetails::KEY_ITEMS] = $taxDetailItemDataObjects;
+        }
+
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRate.php b/app/code/Magento/Tax/Service/V1/Data/TaxRate.php
new file mode 100644
index 00000000000..5784e38b37d
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRate.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+class TaxRate extends \Magento\Framework\Service\Data\AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const KEY_ID = 'id';
+
+    const KEY_COUNTRY_ID = 'country_id';
+
+    const KEY_REGION_ID = 'region_id';
+
+    const KEY_POSTCODE = 'postcode';
+
+    const KEY_ZIP_RANGE = 'zip_range';
+
+    const KEY_PERCENTAGE_RATE = 'percentage_rate';
+
+    const KEY_CODE = 'code';
+    /**#@-*/
+
+    /**
+     * Get id
+     *
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->_get(self::KEY_ID);
+    }
+
+    /**
+     * Get country id
+     *
+     * @return string
+     */
+    public function getCountryId()
+    {
+        return $this->_get(self::KEY_COUNTRY_ID);
+    }
+
+    /**
+     * Get region id
+     *
+     * @return int
+     */
+    public function getRegionId()
+    {
+        return $this->_get(self::KEY_REGION_ID);
+    }
+
+    /**
+     * Get postcode
+     *
+     * @return string|null
+     */
+    public function getPostcode()
+    {
+        return $this->_get(self::KEY_POSTCODE);
+    }
+
+    /**
+     * Get zip range
+     *
+     * @return \Magento\Tax\Service\V1\Data\ZipRange|null
+     */
+    public function getZipRange()
+    {
+        return $this->_get(self::KEY_ZIP_RANGE);
+    }
+
+    /**
+     * Get tax rate in percentage
+     *
+     * @return float
+     */
+    public function getPercentageRate()
+    {
+        return $this->_get(self::KEY_PERCENTAGE_RATE);
+    }
+
+    /**
+     * Get tax rate code
+     *
+     * @return string
+     */
+    public function getCode()
+    {
+        return $this->_get(self::KEY_CODE);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRateBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxRateBuilder.php
new file mode 100644
index 00000000000..25e6e67aa52
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRateBuilder.php
@@ -0,0 +1,151 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\ObjectFactory;
+
+/**
+ * Builder for the TaxRate Service Data Object
+ *
+ * @method TaxRate create()
+ */
+class TaxRateBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * ZipRange builder
+     *
+     * @var ZipRangeBuilder
+     */
+    protected $zipRangeBuilder;
+
+    /**
+     * Initialize dependencies.
+     *
+     * @param ObjectFactory $objectFactory
+     * @param ZipRangeBuilder $zipRangeBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        ZipRangeBuilder $zipRangeBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->zipRangeBuilder = $zipRangeBuilder;
+    }
+
+    /**
+     * Set id
+     *
+     * @param int $id
+     * @return $this
+     */
+    public function setId($id)
+    {
+        $this->_set(TaxRate::KEY_ID, $id);
+        return $this;
+    }
+
+    /**
+     * Set country id
+     *
+     * @param string $countryId
+     * @return $this
+     */
+    public function setCountryId($countryId)
+    {
+        $this->_set(TaxRate::KEY_COUNTRY_ID, $countryId);
+        return $this;
+    }
+
+    /**
+     * Set region id
+     *
+     * @param int $regionId
+     * @return $this
+     */
+    public function setRegionId($regionId)
+    {
+        $this->_set(TaxRate::KEY_REGION_ID, $regionId);
+        return $this;
+    }
+
+    /**
+     * Set postcode
+     *
+     * @param string $postcode
+     * @return $this
+     */
+    public function setPostcode($postcode)
+    {
+        $this->_set(TaxRate::KEY_POSTCODE, $postcode);
+        return $this;
+    }
+
+    /**
+     * Set zip range
+     *
+     * @param \Magento\Tax\Service\V1\Data\ZipRange $zipRange
+     * @return $this
+     */
+    public function setZipRange($zipRange)
+    {
+        $this->_set(TaxRate::KEY_ZIP_RANGE, $zipRange);
+        return $this;
+    }
+
+    /**
+     * Set tax rate in percentage
+     *
+     * @param float $rate
+     * @return $this
+     */
+    public function setPercentageRate($rate)
+    {
+        $this->_set(TaxRate::KEY_PERCENTAGE_RATE, $rate);
+        return $this;
+    }
+
+    /**
+     * Set tax rate code
+     *
+     * @param string $code
+     * @return $this
+     */
+    public function setCode($code)
+    {
+        $this->_set(TaxRate::KEY_CODE, $code);
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        if (array_key_exists(TaxRate::KEY_ZIP_RANGE, $data)) {
+            $data[TaxRate::KEY_ZIP_RANGE] =
+                $this->zipRangeBuilder->populateWithArray($data[TaxRate::KEY_ZIP_RANGE])->create();
+        }
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRule.php b/app/code/Magento/Tax/Service/V1/Data/TaxRule.php
new file mode 100644
index 00000000000..b10c6a3823c
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRule.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObject;
+
+/**
+ * Class TaxRule
+ */
+class TaxRule extends AbstractObject
+{
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
+     */
+    const ID = 'id';
+
+    const CODE = 'code';
+
+    const CUSTOMER_TAX_CLASS_IDS = 'customer_tax_class_ids';
+
+    const PRODUCT_TAX_CLASS_IDS = 'product_tax_class_ids';
+
+    const TAX_RATE_IDS = 'tax_rate_ids';
+
+    const PRIORITY = 'priority';
+
+    const SORT_ORDER = 'sort_order';
+    /**#@-*/
+
+    /**
+     * Get id
+     *
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->_get(self::ID);
+    }
+
+    /**
+     * Get tax rule code
+     *
+     * @return string
+     */
+    public function getCode()
+    {
+        return $this->_get(self::CODE);
+    }
+
+    /**
+     * Get customer tax class id
+     *
+     * @return int[]|null
+     */
+    public function getCustomerTaxClassIds()
+    {
+        return $this->_get(self::CUSTOMER_TAX_CLASS_IDS);
+    }
+
+    /**
+     * Get product tax class id
+     *
+     * @return int[]|null
+     */
+    public function getProductTaxClassIds()
+    {
+        return $this->_get(self::PRODUCT_TAX_CLASS_IDS);
+    }
+
+    /**
+     * Get tax rate ids
+     *
+     * @return int[]|null
+     */
+    public function getTaxRateIds()
+    {
+        return $this->_get(self::TAX_RATE_IDS);
+    }
+
+    /**
+     * Get priority
+     *
+     * @return int
+     */
+    public function getPriority()
+    {
+        return $this->_get(self::PRIORITY);
+    }
+
+    /**
+     * Get sort order.
+     *
+     * @return int
+     */
+    public function getSortOrder()
+    {
+        return $this->_get(self::SORT_ORDER);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
new file mode 100644
index 00000000000..5893130941f
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRuleBuilder.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+use Magento\Framework\Service\Data\ObjectFactory;
+
+/**
+ * Builder for the TaxRule Service Data Object
+ *
+ * @method TaxRule create()
+ */
+class TaxRuleBuilder extends AbstractObjectBuilder
+{
+    /**
+     * TaxRate builder
+     *
+     * @var TaxRateBuilder
+     */
+    protected $taxRateBuilder;
+
+    /**
+     * Initialize dependencies.
+     *
+     * @param ObjectFactory $objectFactory
+     * @param TaxRateBuilder $taxRateBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        TaxRateBuilder $taxRateBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->taxRateBuilder = $taxRateBuilder;
+    }
+    /**
+     * Set id
+     *
+     * @param int $id
+     * @return $this
+     */
+    public function setId($id)
+    {
+        return $this->_set(TaxRule::ID, $id);
+    }
+
+    /**
+     * Set code
+     *
+     * @param String $code
+     * @return $this
+     */
+    public function setCode($code)
+    {
+        return $this->_set(TaxRule::CODE, $code);
+    }
+
+    /**
+     * Set customer tax class ids
+     *
+     * @param int[] $customerTaxClassIds
+     * @return $this
+     */
+    public function setCustomerTaxClassIds($customerTaxClassIds)
+    {
+        return $this->_set(TaxRule::CUSTOMER_TAX_CLASS_IDS, $customerTaxClassIds);
+    }
+
+    /**
+     * Set product tax class ids
+     *
+     * @param int[] $productTaxClassIds
+     * @return $this
+     */
+    public function setProductTaxClassIds($productTaxClassIds)
+    {
+        return $this->_set(TaxRule::PRODUCT_TAX_CLASS_IDS, $productTaxClassIds);
+    }
+
+    /**
+     * Set product tax class ids
+     *
+     * @param int[] $taxRateIds
+     * @return $this
+     */
+    public function setTaxRateIds($taxRateIds)
+    {
+        return $this->_set(TaxRule::TAX_RATE_IDS, $taxRateIds);
+    }
+
+    /**
+     * Set priority
+     *
+     * @param int $priority
+     * @return $this
+     */
+    public function setPriority($priority)
+    {
+        return $this->_set(TaxRule::PRIORITY, $priority);
+    }
+
+    /**
+     * Set sort order.
+     *
+     * @param int $sortOrder
+     * @return $this
+     */
+    public function setSortOrder($sortOrder)
+    {
+        return $this->_set(TaxRule::SORT_ORDER, $sortOrder);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResults.php b/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResults.php
new file mode 100644
index 00000000000..220f15d4b22
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResults.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Customer\Service\V1\Data\SearchResults;
+
+/**
+ * TaxRuleSearchResults Service Data Object used for the search service requests
+ */
+class TaxRuleSearchResults extends SearchResults
+{
+    /**
+     * Get items
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxRule[]
+     */
+    public function getItems()
+    {
+        return parent::getItems();
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilder.php b/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilder.php
new file mode 100644
index 00000000000..2e4571ea420
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilder.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\Data\ObjectFactory;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+use Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder;
+
+/**
+ * Builder for the TaxRuleSearchResults Service Data Object
+ *
+ * @method TaxRuleSearchResults create()
+ */
+class TaxRuleSearchResultsBuilder extends AbstractSearchResultsBuilder
+{
+    /**
+     * Constructor
+     *
+     * @param ObjectFactory $objectFactory
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param TaxRuleBuilder $taxRuleObjectBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        TaxRuleBuilder $taxRuleObjectBuilder
+    ) {
+        parent::__construct($objectFactory, $searchCriteriaBuilder, $taxRuleObjectBuilder);
+    }
+
+    /**
+     * Set tax rule items
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxRule[] $taxRuleItems
+     * @return $this
+     */
+    public function setItems($taxRuleItems)
+    {
+        return parent::setItems($taxRuleItems);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Block/PayflowExpress/ShortcutTest.php b/app/code/Magento/Tax/Service/V1/Data/ZipRange.php
similarity index 63%
rename from dev/tests/unit/testsuite/Magento/Paypal/Block/PayflowExpress/ShortcutTest.php
rename to app/code/Magento/Tax/Service/V1/Data/ZipRange.php
index 90d180eae22..f4af862579b 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Block/PayflowExpress/ShortcutTest.php
+++ b/app/code/Magento/Tax/Service/V1/Data/ZipRange.php
@@ -21,23 +21,36 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Paypal\Block\PayflowExpress;
+namespace Magento\Tax\Service\V1\Data;
 
-class ShortcutTest extends \PHPUnit_Framework_TestCase
+class ZipRange extends \Magento\Framework\Service\Data\AbstractObject
 {
-    /**
-     * @var \Magento\Paypal\Block\PayflowExpress\Shortcut|PHPUnit_Framework_MockObject_MockObject
+    /**#@+
+     * Constants defined for keys of array, makes typos less likely
      */
-    protected $model;
+    const KEY_FROM = 'from';
+
+    const KEY_TO = 'to';
 
-    protected function setUp()
+    /**#@-*/
+
+    /**
+     * Get zip range starting point
+     *
+     * @return int
+     */
+    public function getFrom()
     {
-        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->model = $helper->getObject('Magento\Paypal\Block\PayflowExpress\Shortcut');
+        return $this->_get(self::KEY_FROM);
     }
 
-    public function testGetAlias()
+    /**
+     * Get zip range ending point
+     *
+     * @return int
+     */
+    public function getTo()
     {
-        $this->assertEquals('product.info.addtocart.payflow', $this->model->getAlias());
+        return $this->_get(self::KEY_TO);
     }
 }
diff --git a/app/code/Magento/Tax/Service/V1/Data/ZipRangeBuilder.php b/app/code/Magento/Tax/Service/V1/Data/ZipRangeBuilder.php
new file mode 100644
index 00000000000..aabbca265d7
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/Data/ZipRangeBuilder.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+/**
+ * Builder for the ZipRange Service Data Object
+ *
+ * @method ZipRange create()
+ */
+class ZipRangeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder
+{
+    /**
+     * Set zip range starting point
+     *
+     * @param int $from
+     * @return $this
+     */
+    public function setFrom($from)
+    {
+        $this->_set(ZipRange::KEY_FROM, $from);
+        return $this;
+    }
+
+    /**
+     * Set zip range ending point
+     *
+     * @param int $to
+     * @return $this
+     */
+    public function setTo($to)
+    {
+        $this->_set(ZipRange::KEY_TO, $to);
+        return $this;
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxCalculationService.php b/app/code/Magento/Tax/Service/V1/TaxCalculationService.php
new file mode 100644
index 00000000000..564d817e075
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxCalculationService.php
@@ -0,0 +1,583 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Tax\Model\Calculation;
+use Magento\Tax\Model\Resource\Sales\Order\Tax;
+use Magento\Tax\Service\V1\Data\QuoteDetails;
+use Magento\Tax\Service\V1\Data\QuoteDetails\Item as QuoteDetailsItem;
+use Magento\Tax\Service\V1\Data\TaxDetails;
+use Magento\Tax\Service\V1\Data\TaxDetails\Item as TaxDetailsItem;
+use Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder as TaxDetailsItemBuilder;
+use Magento\Tax\Service\V1\Data\TaxDetailsBuilder;
+use Magento\Store\Model\StoreManagerInterface;
+
+/**
+ * Tax Calculation Service
+ *
+ */
+class TaxCalculationService implements TaxCalculationServiceInterface
+{
+    /**
+     * Tax calculation model
+     *
+     * @var Calculation
+     */
+    protected $calculator;
+
+    /**
+     * Tax configuration object
+     *
+     * @var \Magento\Tax\Model\Config
+     */
+    protected $config;
+
+    /**
+     * Tax Details builder
+     *
+     * @var TaxDetailsBuilder
+     */
+    protected $taxDetailsBuilder;
+
+    /**
+     * Rounding deltas for prices
+     *
+     * @var array
+     * example:
+     *  [
+     *      'type' => [
+     *          'rate' => 'rounding delta',
+     *      ],
+     *  ]
+     */
+    protected $roundingDeltas;
+
+    /**
+     * Tax details item builder
+     *
+     * @var TaxDetailsBuilderItem
+     */
+    protected $taxDetailsItemBuilder;
+
+    /**
+     * @var StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * Item code to Item object array.
+     *
+     * @var QuoteDetailsItem[]
+     */
+    private $keyedItems;
+
+    /**
+     * parent item code to children item array.
+     *
+     * @var QuoteDetailsItem[][]
+     */
+    private $parentToChildren;
+
+    /**
+     * Constructor
+     *
+     * @param Calculation $calculation
+     * @param \Magento\Tax\Model\Config $config
+     * @param TaxDetailsBuilder $taxDetailsBuilder
+     * @param TaxDetailsItemBuilder $taxDetailsItemBuilder
+     * @param StoreManagerInterface $storeManager
+     */
+    public function __construct(
+        Calculation $calculation,
+        \Magento\Tax\Model\Config $config,
+        TaxDetailsBuilder $taxDetailsBuilder,
+        TaxDetailsItemBuilder $taxDetailsItemBuilder,
+        StoreManagerInterface $storeManager
+    ) {
+        $this->calculator = $calculation;
+        $this->config = $config;
+        $this->taxDetailsBuilder = $taxDetailsBuilder;
+        $this->taxDetailsItemBuilder = $taxDetailsItemBuilder;
+        $this->storeManager = $storeManager;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function calculateTax(QuoteDetails $quoteDetails, $storeId = null)
+    {
+        if (is_null($storeId)) {
+            $storeId = $this->storeManager->getStore()->getStoreId();
+        }
+
+        // initial TaxDetails data
+        $taxDetailsData = [
+            TaxDetails::KEY_SUBTOTAL => 0.0,
+            TaxDetails::KEY_TAX_AMOUNT => 0.0,
+            TaxDetails::KEY_DISCOUNT_AMOUNT => 0.0
+        ];
+
+        $items = $quoteDetails->getItems();
+        if (empty($items)) {
+            return $this->taxDetailsBuilder->populateWithArray($taxDetailsData)->create();
+        }
+        $this->computeRelationships($items);
+
+        $addressRequest = $this->getAddressTaxRequest($quoteDetails, $storeId);
+        if ($this->config->priceIncludesTax($storeId)) {
+            $storeRequest = $this->getStoreTaxRequest($storeId);
+            $classIds = [];
+            foreach ($items as $item) {
+                if ($item->getTaxClassId()) {
+                    $classIds[] = $item->getTaxClassId();
+                }
+            }
+            $classIds = array_unique($classIds);
+            $addressRequest->setProductClassId($classIds);
+            $storeRequest->setProductClassId($classIds);
+            if ((bool)$this->config->crossBorderTradeEnabled($storeId)) {
+                $addressRequest->setSameRateAsStore(true);
+            } else {
+                $addressRequest->setSameRateAsStore(
+                    $this->calculator->compareRequests($storeRequest, $addressRequest)
+                );
+            }
+        }
+
+        // init rounding deltas for this quote
+        $this->roundingDeltas = [];
+        $processedItems = [];
+        /** @var QuoteDetailsItem $item */
+        foreach ($this->keyedItems as $item) {
+            if (isset($this->parentToChildren[$item->getCode()])) {
+                $processedChildren = [];
+                foreach ($this->parentToChildren[$item->getCode()] as $child) {
+                    $processedChildren[] = $this->processItem($child, $addressRequest, $storeId);
+                }
+                $processedItemBuilder = $this->calculateParent($processedChildren, $item->getQuantity());
+                $processedItemBuilder->setCode($item->getCode());
+                $processedItemBuilder->setType($item->getType());
+                $processedItem = $processedItemBuilder->create();
+            } else {
+                $processedItem = $this->processItem($item, $addressRequest, $storeId);
+            }
+            $processedItems[] = $processedItem;
+            $taxDetailsData = $this->addSubtotalAmount($taxDetailsData, $processedItem);
+        }
+
+        return $this->taxDetailsBuilder->populateWithArray($taxDetailsData)->setItems($processedItems)->create();
+    }
+
+    /**
+     * Computes relationships between items, primarily the child to parent relationship.
+     *
+     * @param QuoteDetailsItem[] $items
+     * @return void
+     */
+    private function computeRelationships($items)
+    {
+        $this->keyedItems = [];
+        $this->parentToChildren = [];
+        foreach ($items as $item) {
+            if ($item->getParentCode() === null) {
+                $this->keyedItems[$item->getCode()] = $item;
+            } else {
+                $this->parentToChildren[$item->getParentCode()][] = $item;
+            }
+        }
+    }
+
+    /**
+     * Get request for fetching address tax rate
+     *
+     * @param QuoteDetails $quoteDetails
+     * @param int $storeId
+     * @return \Magento\Framework\Object
+     */
+    protected function getAddressTaxRequest(QuoteDetails $quoteDetails, $storeId)
+    {
+        return $this->calculator->getRateRequest(
+            $quoteDetails->getShippingAddress(),
+            $quoteDetails->getBillingAddress(),
+            $quoteDetails->getCustomerTaxClassId(),
+            $storeId
+        );
+    }
+
+    /**
+     * Get request for fetching store tax rate
+     *
+     * @param int $storeId
+     * @return \Magento\Framework\Object
+     */
+    protected function getStoreTaxRequest($storeId)
+    {
+        return $this->calculator->getRateOriginRequest($storeId);
+    }
+
+    /**
+     * Calculate item price and row total with customized rounding level
+     *
+     * @param QuoteDetailsItem $item
+     * @param \Magento\Framework\Object $taxRequest
+     * @param int $storeId
+     * @return TaxDetailsItem|null
+     */
+    protected function processItem(
+        QuoteDetailsItem $item,
+        \Magento\Framework\Object $taxRequest,
+        $storeId
+    ) {
+        switch ($this->config->getAlgorithm($storeId)) {
+            case Calculation::CALC_UNIT_BASE:
+                return $this->unitBaseCalculation($item, $taxRequest, $storeId);
+            case Calculation::CALC_ROW_BASE:
+                return $this->rowBaseCalculation($item, $taxRequest, $storeId);
+            case Calculation::CALC_TOTAL_BASE:
+                return $this->totalBaseCalculation($item, $taxRequest, $storeId);
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Calculate item price and row total including/excluding tax based on unit price rounding level
+     *
+     * @param QuoteDetailsItem $item
+     * @param \Magento\Framework\Object $taxRequest
+     * @param int $storeId
+     * @return TaxDetailsItem
+     */
+    protected function unitBaseCalculation(
+        QuoteDetailsItem $item,
+        \Magento\Framework\Object $taxRequest,
+        $storeId
+    ) {
+        $taxRequest->setProductClassId($item->getTaxClassId());
+        $storeRate = $this->calculator->getStoreRate($taxRequest, $storeId);
+        $rate = $this->calculator->getRate($taxRequest);
+        $quantity = $this->getTotalQuantity($item);
+        $price = $taxPrice = $this->calculator->round($item->getUnitPrice());
+        $subtotal = $taxSubtotal = $this->calcRowTotal($item);
+        if ($item->getTaxIncluded()) {
+            if ($taxRequest->getSameRateAsStore() || ($rate == $storeRate)) {
+                $taxable = $price;
+                $tax = $this->calculator->calcTaxAmount($taxable, $rate, true);
+                $price = $price - $tax;
+                $subtotal = $price * $quantity;
+            } else {
+                $taxPrice = $this->calculatePriceInclTax($price, $storeRate, $rate);
+                $taxable = $taxPrice;
+                $tax = $this->calculator->calcTaxAmount($taxable, $rate, true, true);
+                $price = $taxPrice - $tax;
+                $taxSubtotal = $taxPrice * $quantity;
+                $subtotal = $price * $quantity;
+            }
+        } else {
+            $taxable = $price;
+            $appliedRates = $this->calculator->getAppliedRates($taxRequest);
+            $taxes = [];
+            foreach ($appliedRates as $appliedRate) {
+                $taxRate = $appliedRate['percent'];
+                $taxes[] = $this->calculator->calcTaxAmount($taxable, $taxRate, false);
+            }
+            $tax = array_sum($taxes);
+            $taxPrice = $price + $tax;
+            $taxSubtotal = $taxPrice * $quantity;
+        }
+
+        $this->taxDetailsItemBuilder->setRowTax($tax * $quantity);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($taxPrice);
+        $this->taxDetailsItemBuilder->setRowTotal($subtotal);
+        $this->taxDetailsItemBuilder->setTaxableAmount($taxable);
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * Calculate item price and row total including/excluding tax based on row total price rounding level
+     *
+     * @param QuoteDetailsItem $item
+     * @param \Magento\Framework\Object $taxRequest
+     * @param int $storeId
+     * @return TaxDetailsItem
+     */
+    protected function rowBaseCalculation(
+        QuoteDetailsItem $item,
+        \Magento\Framework\Object $taxRequest,
+        $storeId
+    ) {
+        $taxRequest->setProductClassId($item->getTaxClassId());
+        $storeRate = $this->calculator->getStoreRate($taxRequest, $storeId);
+        $rate = $this->calculator->getRate($taxRequest);
+        $quantity = $this->getTotalQuantity($item);
+        $price = $this->calculator->round($item->getUnitPrice());
+        $subtotal = $this->calcRowTotal($item);
+
+        if ($item->getTaxIncluded()) {
+            if ($taxRequest->getSameRateAsStore() || ($rate == $storeRate)) {
+                $taxable = $subtotal;
+                $rowTax = $this->calculator->calcTaxAmount($taxable, $rate, true, true);
+                $taxPrice = $price;
+                $taxSubtotal = $subtotal;
+                $subtotal = $this->calculator->round($subtotal - $rowTax);
+                $price = $this->calculator->round($subtotal / $quantity);
+            } else {
+                $taxPrice = $this->calculatePriceInclTax($price, $storeRate, $rate);
+                $tax = $this->calculator->calcTaxAmount($taxPrice, $rate, true, true);
+                $price = $taxPrice - $tax;
+                $taxable = $taxPrice * $quantity;
+                $taxSubtotal = $taxPrice * $quantity;
+                $rowTax = $this->calculator->calcTaxAmount($taxable, $rate, true, true);
+                $subtotal = $taxSubtotal - $rowTax;
+            }
+        } else {
+            $taxable = $subtotal;
+            $appliedRates = $this->calculator->getAppliedRates($taxRequest);
+            $rowTaxes = [];
+            foreach ($appliedRates as $appliedRate) {
+                $taxRate = $appliedRate['percent'];
+                $rowTaxes[] = $this->calculator->calcTaxAmount($taxable, $taxRate, false, true);
+            }
+            $rowTax = array_sum($rowTaxes);
+            $taxSubtotal = $subtotal + $rowTax;
+            $taxPrice = $this->calculator->round($taxSubtotal / $quantity);
+        }
+
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($taxPrice);
+        $this->taxDetailsItemBuilder->setRowTotal($subtotal);
+        $this->taxDetailsItemBuilder->setTaxableAmount($taxable);
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * Calculate item price and row total including/excluding tax based on total price rounding level
+     *
+     * @param QuoteDetailsItem $item
+     * @param \Magento\Framework\Object $taxRequest
+     * @param int $storeId
+     * @return TaxDetailsItem
+     */
+    protected function totalBaseCalculation(
+        QuoteDetailsItem $item,
+        \Magento\Framework\Object $taxRequest,
+        $storeId
+    ) {
+        $taxRequest->setProductClassId($item->getTaxClassId());
+        $storeRate = $this->calculator->getStoreRate($taxRequest, $storeId);
+        $rate = $this->calculator->getRate($taxRequest);
+        $quantity = $this->getTotalQuantity($item);
+        $price = $this->calculator->round($item->getUnitPrice());
+        $subtotal = $taxSubtotal = $this->calcRowTotal($item);
+
+        if ($item->getTaxIncluded()) {
+            if ($taxRequest->getSameRateAsStore() || ($rate == $storeRate)) {
+                $taxable = $subtotal;
+                $rowTaxExact = $this->calculator->calcTaxAmount($taxable, $rate, true, false);
+                $rowTax = $this->deltaRound($rowTaxExact, $rate, true);
+                $subtotal = $subtotal - $rowTax;
+                $taxPrice = $price;
+                $price = $this->calculator->round($subtotal / $quantity);
+
+            } else {
+                $taxPrice = $this->calculatePriceInclTax($price, $storeRate, $rate);
+                $tax = $this->calculator->calcTaxAmount($taxPrice, $rate, true, true);
+                $price = $taxPrice - $tax;
+                $taxSubtotal = $taxable = $taxPrice * $quantity;
+                $rowTax =
+                    $this->deltaRound($this->calculator->calcTaxAmount($taxable, $rate, true, false), $rate, true);
+                $subtotal = $taxSubtotal - $rowTax;
+            }
+        } else {
+            $taxable = $subtotal;
+            $appliedRates = $this->calculator->getAppliedRates($taxRequest);
+            $rowTaxes = [];
+            foreach ($appliedRates as $appliedRate) {
+                $taxId = $appliedRate['id'];
+                $taxRate = $appliedRate['percent'];
+                $rowTaxes[] = $this->deltaRound(
+                    $this->calculator->calcTaxAmount($taxable, $taxRate, false, false),
+                    $taxId,
+                    false
+                );
+            }
+            $rowTax = array_sum($rowTaxes);
+            $taxSubtotal = $subtotal + $rowTax;
+            $taxPrice = $this->calculator->round($taxSubtotal / $quantity);
+        }
+
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($taxPrice);
+        $this->taxDetailsItemBuilder->setRowTotal($subtotal);
+        $this->taxDetailsItemBuilder->setTaxableAmount($taxable);
+        $this->taxDetailsItemBuilder->setCode($item->getCode());
+        $this->taxDetailsItemBuilder->setType($item->getType());
+        $this->taxDetailsItemBuilder->setTaxPercent($rate);
+
+        return $this->taxDetailsItemBuilder->create();
+    }
+
+    /**
+     * Round price based on previous rounding operation delta
+     *
+     * @param float $price
+     * @param string $rate
+     * @param bool $direction
+     * @param string $type
+     * @return float
+     */
+    protected function deltaRound($price, $rate, $direction, $type = 'regular')
+    {
+        if ($price) {
+            $rate = (string)$rate;
+            $type = $type . $direction;
+            // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
+            $delta = isset($this->roundingDeltas[$type][$rate]) ?
+                $this->roundingDeltas[$type][$rate] :
+                0.000001;
+            $price += $delta;
+            $roundPrice = $this->calculator->round($price);
+            $this->roundingDeltas[$type][$rate] = $price - $roundPrice;
+            $price = $roundPrice;
+        }
+        return $price;
+    }
+
+    /**
+     * Calculate row information for item based on children calculation
+     *
+     * @param TaxDetailsItem[] $children
+     * @param int $quantity
+     * @return TaxDetailsItemBuilder
+     */
+    protected function calculateParent($children, $quantity)
+    {
+        $rowTotal = 0.00;
+        $rowTax = 0.00;
+        $taxableAmount = 0.00;
+
+        foreach ($children as $child) {
+            $rowTotal += $child->getRowTotal();
+            $rowTax += $child->getRowTax();
+            $taxableAmount += $child->getTaxableAmount();
+        }
+
+        $rowTotalInclTax = $rowTotal + $rowTax;
+        $price = $this->calculator->round($rowTotal / $quantity);
+        $priceInclTax = $this->calculator->round($rowTotalInclTax / $quantity);
+
+        $this->taxDetailsItemBuilder->setPrice($price);
+        $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
+        $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
+        $this->taxDetailsItemBuilder->setRowTax($rowTax);
+        $this->taxDetailsItemBuilder->setTaxableAmount($taxableAmount);
+
+        return $this->taxDetailsItemBuilder;
+    }
+
+    /**
+     * Given a store price that includes tax at the store rate, this function will back out the store's tax, and add in
+     * the customer's tax.  Returns this new price which is the customer's price including tax.
+     *
+     * @param float $storePriceInclTax
+     * @param float $storeRate
+     * @param float $customerRate
+     * @return float
+     */
+    protected function calculatePriceInclTax($storePriceInclTax, $storeRate, $customerRate)
+    {
+        $storeTax = $this->calculator->calcTaxAmount($storePriceInclTax, $storeRate, true, false);
+        $priceExclTax = $storePriceInclTax - $storeTax;
+        $customerTax = $this->calculator->calcTaxAmount($priceExclTax, $customerRate, false, false);
+        $customerPriceInclTax = $this->calculator->round($priceExclTax + $customerTax);
+        return $customerPriceInclTax;
+    }
+
+    /**
+     * Add row total item amount to subtotal
+     *
+     * @param array $taxDetailsData
+     * @param TaxDetailsItem $item
+     * @return array
+     */
+    protected function addSubtotalAmount($taxDetailsData, TaxDetailsItem $item)
+    {
+        $taxDetailsData[TaxDetails::KEY_SUBTOTAL]
+            = $taxDetailsData[TaxDetails::KEY_SUBTOTAL] + $item->getRowTotal();
+
+        $taxDetailsData[TaxDetails::KEY_TAX_AMOUNT]
+            = $taxDetailsData[TaxDetails::KEY_TAX_AMOUNT] + $item->getRowTax();
+
+        $taxDetailsData[TaxDetails::KEY_DISCOUNT_AMOUNT]
+            = $taxDetailsData[TaxDetails::KEY_DISCOUNT_AMOUNT] + $item->getDiscountAmount();
+
+        return $taxDetailsData;
+    }
+
+    /**
+     * Calculates the total quantity for this item.
+     *
+     * What this really means is that if this is a child item, it return the parent quantity times
+     * the child quantity and return that as the child's quantity.
+     *
+     * @param QuoteDetailsItem $item
+     * @return float
+     */
+    protected function getTotalQuantity(QuoteDetailsItem $item)
+    {
+        if ($item->getParentCode()) {
+            $parentQuantity = $this->keyedItems[$item->getParentCode()]->getQuantity();
+            return $parentQuantity * $item->getQuantity();
+        }
+        return $item->getQuantity();
+    }
+
+    /**
+     * Calculate the row total for an item
+     *
+     * @param QuoteDetailsItem $item
+     * @return float
+     */
+    protected function calcRowTotal(QuoteDetailsItem $item)
+    {
+        $qty = $this->getTotalQuantity($item);
+
+        // Round unit price before multiplying to prevent losing 1 cent on subtotal
+        $total = $this->calculator->round($item->getUnitPrice()) * $qty;
+
+        return $this->calculator->round($total);
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
new file mode 100644
index 00000000000..9b5bf8a87b4
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxCalculationServiceInterface.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+interface TaxCalculationServiceInterface
+{
+    /**
+     * Calculate Tax
+     *
+     * @param \Magento\Tax\Service\V1\Data\QuoteDetails $quoteDetails
+     * @param null|int $storeId
+     * @return \Magento\Tax\Service\V1\Data\TaxDetails
+     */
+    public function calculateTax(\Magento\Tax\Service\V1\Data\QuoteDetails $quoteDetails, $storeId);
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxRateService.php b/app/code/Magento/Tax/Service/V1/TaxRateService.php
new file mode 100644
index 00000000000..b9de69c6175
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxRateService.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Tax\Model\Calculation\Rate\Converter;
+use Magento\Tax\Service\V1\Data\TaxRate as TaxRateDataObject;
+use Magento\Tax\Model\Calculation\Rate as RateModel;
+use Magento\Tax\Service\V1\Data\TaxRateBuilder;
+use Magento\Framework\Exception\InputException;
+use Magento\Tax\Model\Calculation\RateRegistry;
+
+/**
+ * Handles tax rate CRUD operations
+ *
+ */
+class TaxRateService implements TaxRateServiceInterface
+{
+    /**
+     * Tax rate model and tax rate data object converter
+     *
+     * @var  Converter
+     */
+    protected $converter;
+
+    /**
+     * Tax rate data object builder
+     *
+     * @var  TaxRateBuilder
+     */
+    protected $rateBuilder;
+
+    /**
+     * Tax rate registry
+     *
+     * @var  RateRegistry
+     */
+    protected $rateRegistry;
+
+    /**
+     * Constructor
+     *
+     * @param TaxRateBuilder $rateBuilder
+     * @param Converter $converter
+     * @param RateRegistry $rateRegistry
+     */
+    public function __construct(
+        TaxRateBuilder $rateBuilder,
+        Converter $converter,
+        RateRegistry $rateRegistry
+    ) {
+        $this->rateBuilder = $rateBuilder;
+        $this->converter = $converter;
+        $this->rateRegistry = $rateRegistry;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function createTaxRate(TaxRateDataObject $taxRate)
+    {
+        $rateModel = $this->saveTaxRate($taxRate);
+        return $this->converter->createTaxRateDataObjectFromModel($rateModel);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTaxRate($rateId)
+    {
+        $rateModel = $this->rateRegistry->retrieveTaxRate($rateId);
+        return $this->converter->createTaxRateDataObjectFromModel($rateModel);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function updateTaxRate(TaxRateDataObject $taxRate)
+    {
+        // Only update existing tax rates
+        $this->rateRegistry->retrieveTaxRate($taxRate->getId());
+
+        $this->saveTaxRate($taxRate);
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function deleteTaxRate($rateId)
+    {
+        $rateModel = $this->rateRegistry->retrieveTaxRate($rateId);
+        $rateModel->delete();
+        $this->rateRegistry->removeTaxRate($rateId);
+        return true;
+    }
+
+    /**
+     * Save Tax Rate
+     *
+     * @param TaxRateDataObject $taxRate
+     * @throws InputException
+     * @throws \Magento\Framework\Model\Exception
+     * @return RateModel
+     */
+    protected function saveTaxRate(TaxRateDataObject $taxRate)
+    {
+        $this->validate($taxRate);
+        $taxRateModel = $this->converter->createTaxRateModel($taxRate);
+        $taxRateModel->save();
+        $this->rateRegistry->registerTaxRate($taxRateModel);
+        return $taxRateModel;
+    }
+
+    /**
+     * Validate tax rate
+     *
+     * @param TaxRateDataObject $taxRate
+     * @throws InputException
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    private function validate(TaxRateDataObject $taxRate)
+    {
+        $exception = new InputException();
+        if (!\Zend_Validate::is(trim($taxRate->getCountryId()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'country_id']);
+        }
+        if (!\Zend_Validate::is(trim($taxRate->getRegionId()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'region_id']);
+        }
+        if (!\Zend_Validate::is(trim($taxRate->getPercentageRate()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'percentage_rate']);
+        }
+        if (!\Zend_Validate::is(trim($taxRate->getCode()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'code']);
+        }
+
+        if ($taxRate->getZipRange()) {
+            $zipRangeFromTo = [
+                'zip_from' => $taxRate->getZipRange()->getFrom(),
+                'zip_to' => $taxRate->getZipRange()->getTo()
+            ];
+            foreach ($zipRangeFromTo as $key => $value) {
+                if (!is_numeric($value) || $value < 0) {
+                    $exception->addError(
+                        InputException::INVALID_FIELD_VALUE,
+                        ['fieldName' => $key, 'value' => $value]
+                    );
+                }
+            }
+            if ($zipRangeFromTo['zip_from'] > $zipRangeFromTo['zip_to']) {
+                $exception->addError('Range To should be equal or greater than Range From.');
+            }
+
+        } else {
+            if (!\Zend_Validate::is(trim($taxRate->getPostcode()), 'NotEmpty')) {
+                $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => 'postcode']);
+            }
+        }
+        if ($exception->wasErrorAdded()) {
+            throw $exception;
+        }
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxRateServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxRateServiceInterface.php
new file mode 100644
index 00000000000..23d0c3e575e
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxRateServiceInterface.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+interface TaxRateServiceInterface
+{
+    /**
+     * Create tax rate
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxRate $taxRate
+     * @return \Magento\Tax\Service\V1\Data\TaxRate
+     * @throws \Magento\Framework\Exception\InputException If input is invalid or required input is missing.
+     * @throws \Exception If something went wrong while creating the TaxRate.
+     */
+    public function createTaxRate(\Magento\Tax\Service\V1\Data\TaxRate $taxRate);
+
+    /**
+     * Get tax rate
+     *
+     * @param int $rateId
+     * @return \Magento\Tax\Service\V1\Data\TaxRate
+     * @throws \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function getTaxRate($rateId);
+
+    /**
+     * Update given tax rate
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxRate $taxRate
+     * @return bool
+     * @throws \Magento\Framework\Exception\InputException If input is invalid or required input is missing.
+     * @throws \Magento\Framework\Exception\NoSuchEntityException If the TaxRate to update can't be found in the system.
+     * @throws \Exception If something went wrong while performing the update.
+     */
+    public function updateTaxRate(\Magento\Tax\Service\V1\Data\TaxRate $taxRate);
+
+    /**
+     * Delete tax rate
+     *
+     * @param int $rateId
+     * @return bool
+     * @throws \Magento\Framework\Exception\NoSuchEntityException If no TaxRate with the given ID can be found.
+     * @throws \Exception If something went wrong while performing the delete.
+     */
+    public function deleteTaxRate($rateId);
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxRuleService.php b/app/code/Magento/Tax/Service/V1/TaxRuleService.php
new file mode 100644
index 00000000000..3f51a1fab2e
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxRuleService.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Framework\Service\V1\Data\SearchCriteria;
+use Magento\Tax\Model\Calculation\TaxRuleConverter;
+use Magento\Tax\Service\V1\Data\TaxRule;
+use Magento\Tax\Service\V1\Data\TaxRuleBuilder;
+use Magento\Tax\Model\Calculation\TaxRuleRegistry;
+use Magento\Framework\Exception\InputException;
+use Magento\Tax\Model\Calculation\Rule as TaxRuleModel;
+
+class TaxRuleService implements TaxRuleServiceInterface
+{
+    /**
+     * Builder for TaxRule data objects.
+     *
+     * @var TaxRuleBuilder
+     */
+    protected $taxRuleBuilder;
+
+    /**
+     * @var TaxRuleConverter
+     */
+    protected $converter;
+
+    /**
+     * @var TaxRuleRegistry
+     */
+    protected $taxRuleRegistry;
+
+    /**
+     * @param TaxRuleBuilder $taxRuleBuilder
+     * @param TaxRuleConverter $converter
+     * @param TaxRuleRegistry $taxRuleRegistry
+     */
+    public function __construct(
+        TaxRuleBuilder $taxRuleBuilder,
+        TaxRuleConverter $converter,
+        TaxRuleRegistry $taxRuleRegistry
+    ) {
+        $this->taxRuleBuilder = $taxRuleBuilder;
+        $this->converter = $converter;
+        $this->taxRuleRegistry = $taxRuleRegistry;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function createTaxRule(TaxRule $taxRule)
+    {
+        $taxRuleModel = $this->saveTaxRule($taxRule);
+        return $this->converter->createTaxRuleDataObjectFromModel($taxRuleModel);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function updateTaxRule(TaxRule $rule)
+    {
+        // Only update existing tax rules
+        $this->taxRuleRegistry->retrieveTaxRule($rule->getId());
+
+        $this->saveTaxRule($rule);
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function deleteTaxRule($ruleId)
+    {
+        $ruleModel = $this->taxRuleRegistry->retrieveTaxRule($ruleId);
+        $ruleModel->delete();
+        $this->taxRuleRegistry->removeTaxRule($ruleId);
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTaxRule($taxRuleId)
+    {
+        $taxRuleModel = $this->taxRuleRegistry->retrieveTaxRule($taxRuleId);
+        return $this->converter->createTaxRuleDataObjectFromModel($taxRuleModel);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function searchTaxRules(SearchCriteria $searchCriteria)
+    {
+        // TODO: Implement searchTaxRules() method.
+    }
+
+    /**
+     * Save Tax Rule
+     *
+     * @param TaxRule $taxRule
+     * @return TaxRuleModel
+     * @throws InputException
+     * @throws \Magento\Framework\Model\Exception
+     */
+    protected function saveTaxRule(TaxRule $taxRule)
+    {
+        $this->validate($taxRule);
+        $taxRuleModel = $this->converter->createTaxRuleModel($taxRule);
+        $taxRuleModel->save();
+        $this->taxRuleRegistry->registerTaxRule($taxRuleModel);
+        return $taxRuleModel;
+    }
+
+    /**
+     * Validate tax rule
+     *
+     * @param TaxRule $taxRule
+     * @return void
+     * @throws InputException
+     *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    private function validate(TaxRule $taxRule)
+    {
+        $exception = new InputException();
+
+        // SortOrder is required and must be 0 or greater
+        if (!\Zend_Validate::is(trim($taxRule->getSortOrder()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::SORT_ORDER]);
+        }
+        if (!\Zend_Validate::is(trim($taxRule->getSortOrder()), 'GreaterThan', [-1])) {
+            $exception->addError(
+                InputException::INVALID_FIELD_MIN_VALUE,
+                ['fieldName' => TaxRule::SORT_ORDER, 'value' => $taxRule->getSortOrder(), 'minValue' => 0]
+            );
+        }
+
+        // Priority is required and must be 0 or greater
+        if (!\Zend_Validate::is(trim($taxRule->getPriority()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::PRIORITY]);
+        }
+        if (!\Zend_Validate::is(trim($taxRule->getPriority()), 'GreaterThan', [-1])) {
+            $exception->addError(
+                InputException::INVALID_FIELD_MIN_VALUE,
+                ['fieldName' => TaxRule::PRIORITY, 'value' => $taxRule->getPriority(), 'minValue' => 0]
+            );
+        }
+
+        // Code is required
+        if (!\Zend_Validate::is(trim($taxRule->getCode()), 'NotEmpty')) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::CODE]);
+        }
+        // customer tax class ids is required
+        if (($taxRule->getCustomerTaxClassIds() === null) || !$taxRule->getCustomerTaxClassIds()) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::CUSTOMER_TAX_CLASS_IDS]);
+        }
+        // product tax class ids is required
+        if (($taxRule->getProductTaxClassIds() === null) || !$taxRule->getProductTaxClassIds()) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::PRODUCT_TAX_CLASS_IDS]);
+        }
+        // tax rate ids is required
+        if (($taxRule->getTaxRateIds() === null) || !$taxRule->getTaxRateIds()) {
+            $exception->addError(InputException::REQUIRED_FIELD, ['fieldName' => TaxRule::TAX_RATE_IDS]);
+        }
+
+        // throw exception if errors were found
+        if ($exception->wasErrorAdded()) {
+            throw $exception;
+        }
+    }
+}
diff --git a/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php b/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
new file mode 100644
index 00000000000..7f031b65a0c
--- /dev/null
+++ b/app/code/Magento/Tax/Service/V1/TaxRuleServiceInterface.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+/**
+ * Interface TaxRuleServiceInterface
+ */
+interface TaxRuleServiceInterface
+{
+    /**
+     * Create TaxRule
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxRule $rule
+     * @return \Magento\Tax\Service\V1\Data\TaxRule
+     * @throws \Magento\Framework\Exception\InputException If input is invalid or required input is missing.
+     * @throws \Exception If something went wrong while performing the update.
+     */
+    public function createTaxRule(\Magento\Tax\Service\V1\Data\TaxRule $rule);
+
+    /**
+     * Update TaxRule
+     *
+     * @param \Magento\Tax\Service\V1\Data\TaxRule $rule
+     * @return bool
+     * @throws \Magento\Framework\Exception\InputException If input is invalid or required input is missing.
+     * @throws \Magento\Framework\Exception\NoSuchEntityException If the TaxRule to update can't be found in the system.
+     * @throws \Exception If something went wrong while performing the update.
+     */
+    public function updateTaxRule(\Magento\Tax\Service\V1\Data\TaxRule $rule);
+
+    /**
+     * Delete TaxRule
+     *
+     * @param int $ruleId
+     * @return bool
+     * @throws \Magento\Framework\Exception\NoSuchEntityException If no TaxRate with the given ID can be found.
+     * @throws \Exception If something went wrong while performing the delete.
+     */
+    public function deleteTaxRule($ruleId);
+
+    /**
+     * Get TaxRule
+     *
+     * @param int $ruleId
+     * @return \Magento\Tax\Service\V1\Data\TaxRule
+     */
+    public function getTaxRule($ruleId);
+
+    /**
+     * Search TaxRules
+     *
+     * @param \Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria
+     * @return \Magento\Tax\Service\V1\Data\TaxRuleSearchResults containing Data\TaxRule objects
+     * @throws \Magento\Framework\Exception\InputException If there is a problem with the input
+     */
+    public function searchTaxRules(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria);
+}
diff --git a/app/code/Magento/Tax/etc/di.xml b/app/code/Magento/Tax/etc/di.xml
index 2e0a6513eac..f2bf3f08de7 100644
--- a/app/code/Magento/Tax/etc/di.xml
+++ b/app/code/Magento/Tax/etc/di.xml
@@ -24,6 +24,12 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
+    <preference for="Magento\Tax\Service\V1\TaxRateServiceInterface"
+                type="Magento\Tax\Service\V1\TaxRateService"/>
+    <preference for="Magento\Tax\Service\V1\TaxRuleServiceInterface"
+                type="Magento\Tax\Service\V1\TaxRuleService"/>
+    <preference for="Magento\Tax\Service\V1\TaxCalculationServiceInterface"
+                type="Magento\Tax\Service\V1\TaxCalculationService"/>
     <type name="Magento\Tax\Helper\Data">
         <arguments>
             <argument name="taxConfig" xsi:type="object">Magento\Tax\Model\Config\Proxy</argument>
diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml
index 4a737678df7..45ddd128035 100644
--- a/app/code/Magento/Tax/etc/module.xml
+++ b/app/code/Magento/Tax/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Tax" version="1.6.0.6" active="true">
+    <module name="Magento_Tax" schema_version="1.6.0.6" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Customer"/>
diff --git a/app/code/Magento/Theme/etc/module.xml b/app/code/Magento/Theme/etc/module.xml
index 7cdd4ecce17..4cb1528cf6d 100644
--- a/app/code/Magento/Theme/etc/module.xml
+++ b/app/code/Magento/Theme/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Theme" version="1.6.0.0" active="true">
+    <module name="Magento_Theme" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml
index f8b7f811b03..d8d091d867e 100644
--- a/app/code/Magento/Translation/etc/module.xml
+++ b/app/code/Magento/Translation/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Translation" version="1.0.0.1" active="true">
+    <module name="Magento_Translation" schema_version="1.0.0.1" active="true">
         <sequence>
             <module name="Magento_Core"/>
         </sequence>
diff --git a/app/code/Magento/Ups/etc/module.xml b/app/code/Magento/Ups/etc/module.xml
index 7b1efb8d8b4..5e3c327c26d 100644
--- a/app/code/Magento/Ups/etc/module.xml
+++ b/app/code/Magento/Ups/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Ups" version="2.0.0.0" active="true">
+    <module name="Magento_Ups" schema_version="2.0.0.0" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Core"/>
diff --git a/app/code/Magento/UrlRewrite/etc/module.xml b/app/code/Magento/UrlRewrite/etc/module.xml
index 974b6b16187..61de1204f9f 100644
--- a/app/code/Magento/UrlRewrite/etc/module.xml
+++ b/app/code/Magento/UrlRewrite/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_UrlRewrite" version="1.0.0.0" active="true">
+    <module name="Magento_UrlRewrite" schema_version="1.0.0.0" active="true">
         <depends>
             <module name="Magento_Catalog" />
             <module name="Magento_Core" />
diff --git a/app/code/Magento/User/etc/module.xml b/app/code/Magento/User/etc/module.xml
index 77029c20545..a20a3449928 100644
--- a/app/code/Magento/User/etc/module.xml
+++ b/app/code/Magento/User/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_User" version="1.6.1.6" active="true">
+    <module name="Magento_User" schema_version="1.6.1.6" active="true">
         <sequence>
             <module name="Magento_Backend"/>
         </sequence>
diff --git a/app/code/Magento/Usps/etc/module.xml b/app/code/Magento/Usps/etc/module.xml
index 970190b71e8..fb7bdbc8ba9 100644
--- a/app/code/Magento/Usps/etc/module.xml
+++ b/app/code/Magento/Usps/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Usps" version="2.0.0.0" active="true">
+    <module name="Magento_Usps" schema_version="2.0.0.0" active="true">
         <depends>
             <module name="Magento_Store"/>
             <module name="Magento_Shipping"/>
diff --git a/app/code/Magento/Webapi/Controller/Login.php b/app/code/Magento/Webapi/Controller/Login.php
new file mode 100644
index 00000000000..d3ff9792e33
--- /dev/null
+++ b/app/code/Magento/Webapi/Controller/Login.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Webapi\Controller;
+
+use Magento\Authz\Model\UserIdentifier;
+use Magento\Customer\Service\V1\CustomerAccountServiceInterface;
+use Magento\Framework\Exception\AuthenticationException;
+use Magento\Webapi\Exception;
+use Magento\Webapi\Exception as HttpException;
+
+/**
+ * Login controller
+ */
+class Login extends \Magento\Framework\App\Action\Action
+{
+    /**
+     * @var \Magento\Framework\Session\Generic
+     */
+    protected $session;
+
+    /**
+     * @var CustomerAccountServiceInterface
+     */
+    protected $customerAccountService;
+
+    /**
+     * @var \Magento\Webapi\Controller\Rest\Request\Deserializer\Factory
+     */
+    protected $deserializerFactory;
+
+    /**
+     * Initialize Login Service
+     *
+     * @param \Magento\Framework\App\Action\Context $context
+     * @param \Magento\Framework\Session\Generic $session
+     * @param \Magento\Webapi\Controller\Rest\Request\Deserializer\Factory $deserializerFactory
+     * @param CustomerAccountServiceInterface $customerAccountService
+     */
+    public function __construct(
+        \Magento\Framework\App\Action\Context $context,
+        \Magento\Framework\Session\Generic $session,
+        \Magento\Webapi\Controller\Rest\Request\Deserializer\Factory $deserializerFactory,
+        CustomerAccountServiceInterface $customerAccountService
+    ) {
+        parent::__construct($context);
+        $this->session = $session;
+        $this->deserializerFactory = $deserializerFactory;
+        $this->customerAccountService = $customerAccountService;
+    }
+
+    /**
+     * Login registered users and initiate a session. Send back the session id.
+     *
+     * Expects a POST. ex for JSON  {"username":"user@magento.com", "password":"userpassword"}
+     *
+     * @return void
+     */
+    public function indexAction()
+    {
+        $contentTypeHeaderValue = $this->getRequest()->getHeader('Content-Type');
+        $contentType = $this->getContentType($contentTypeHeaderValue);
+        $loginData = null;
+        try {
+            $loginData = $this->deserializerFactory
+                ->get($contentType)
+                ->deserialize($this->getRequest()->getRawBody());
+        } catch (Exception $e) {
+            $this->getResponse()->setHttpResponseCode($e->getCode());
+            return;
+        }
+        if (!$loginData || $this->getRequest()->getMethod() !== \Magento\Webapi\Model\Rest\Config::HTTP_METHOD_POST) {
+            $this->getResponse()->setHttpResponseCode(HttpException::HTTP_BAD_REQUEST);
+            return;
+        }
+        $customerData = null;
+        try {
+            $customerData = $this->customerAccountService->authenticate($loginData['username'], $loginData['password']);
+        } catch (AuthenticationException $e) {
+            $this->getResponse()->setHttpResponseCode(HttpException::HTTP_UNAUTHORIZED);
+            return;
+        }
+        $this->session->start('frontend');
+        $this->session->setUserId($customerData->getId());
+        $this->session->setUserType(UserIdentifier::USER_TYPE_CUSTOMER);
+        $this->session->regenerateId(true);
+    }
+
+    /**
+     * Initiate a session for unregistered users. Send back the session id.
+     *
+     * @return void
+     */
+    public function anonymousAction()
+    {
+        $this->session->start('frontend');
+        $this->session->setUserId(0);
+        $this->session->setUserType(UserIdentifier::USER_TYPE_GUEST);
+        $this->session->regenerateId(true);
+    }
+
+    /**
+     * Get Content-Type value of request given the $header value.
+     *
+     * TODO: Remove this method if \Magento\Webapi\Controller\Rest\Request can be injected instead of
+     * Magento\Framework\App\Request\Http which is injected by core di.xml
+     *
+     * @param string $headerValue
+     * @return string
+     * @throws \Magento\Webapi\Exception
+     */
+    protected function getContentType($headerValue)
+    {
+        if (!preg_match('~^([a-z\d/\-+.]+)(?:; *charset=(.+))?$~Ui', $headerValue, $matches)) {
+            return null;
+        }
+        // request encoding check if it is specified in header
+        if (isset($matches[2]) && \Magento\Webapi\Controller\Rest\Request::REQUEST_CHARSET != strtolower($matches[2])) {
+            return null;
+        }
+
+        return $matches[1];
+    }
+}
diff --git a/app/code/Magento/Webapi/Controller/Rest.php b/app/code/Magento/Webapi/Controller/Rest.php
index b405110d7d7..7bcca2bfe3b 100644
--- a/app/code/Magento/Webapi/Controller/Rest.php
+++ b/app/code/Magento/Webapi/Controller/Rest.php
@@ -23,16 +23,19 @@
  */
 namespace Magento\Webapi\Controller;
 
+use Magento\Authz\Model\UserIdentifier;
 use Magento\Authz\Service\AuthorizationV1Interface as AuthorizationService;
+use Magento\Framework\Exception\AuthorizationException;
 use Magento\Framework\Service\Data\AbstractObject;
 use Magento\Framework\Service\Data\Eav\AbstractObject as EavAbstractObject;
 use Magento\Framework\Service\EavDataObjectConverter;
 use Magento\Webapi\Controller\Rest\Request as RestRequest;
 use Magento\Webapi\Controller\Rest\Response as RestResponse;
+use Magento\Webapi\Controller\Rest\Response\PartialResponseProcessor;
 use Magento\Webapi\Controller\Rest\Router;
-use Magento\Webapi\Model\PathProcessor;
 use Magento\Webapi\Model\Config\Converter;
-use Magento\Framework\Exception\AuthorizationException;
+use Magento\Webapi\Model\PathProcessor;
+use Magento\Webapi\Controller\Rest\Router\Route;
 
 /**
  * Front controller for WebAPI REST area.
@@ -40,12 +43,16 @@ use Magento\Framework\Exception\AuthorizationException;
  * TODO: Consider warnings suppression removal
  *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class Rest implements \Magento\Framework\App\FrontControllerInterface
 {
     /** @var Router */
     protected $_router;
 
+    /** @var Route */
+    protected $_route;
+
     /** @var RestRequest */
     protected $_request;
 
@@ -84,6 +91,16 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
      */
     protected $areaList;
 
+    /**
+     * @var PartialResponseProcessor
+     */
+    protected $partialResponseProcessor;
+
+    /**
+     * @var \Magento\Framework\Session\Generic
+     */
+    protected $session;
+
     /**
      * Initialize dependencies
      *
@@ -100,6 +117,8 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
      * @param ErrorProcessor $errorProcessor
      * @param PathProcessor $pathProcessor
      * @param \Magento\Framework\App\AreaList $areaList
+     * @param PartialResponseProcessor $partialResponseProcessor
+     * @param \Magento\Framework\Session\Generic $session
      *
      * TODO: Consider removal of warning suppression
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -117,7 +136,9 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
         ServiceArgsSerializer $serializer,
         ErrorProcessor $errorProcessor,
         PathProcessor $pathProcessor,
-        \Magento\Framework\App\AreaList $areaList
+        \Magento\Framework\App\AreaList $areaList,
+        PartialResponseProcessor $partialResponseProcessor,
+        \Magento\Framework\Session\Generic $session
     ) {
         $this->_router = $router;
         $this->_request = $request;
@@ -132,6 +153,8 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
         $this->_errorProcessor = $errorProcessor;
         $this->_pathProcessor = $pathProcessor;
         $this->areaList = $areaList;
+        $this->partialResponseProcessor = $partialResponseProcessor;
+        $this->session = $session;
     }
 
     /**
@@ -150,22 +173,8 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
             if (!$this->_appState->isInstalled()) {
                 throw new \Magento\Webapi\Exception(__('Magento is not yet installed'));
             }
-            $oauthRequest = $this->_oauthHelper->prepareRequest($this->_request);
-            $consumerId = $this->_oauthService->validateAccessTokenRequest(
-                $oauthRequest,
-                $this->_oauthHelper->getRequestUrl($this->_request),
-                $this->_request->getMethod()
-            );
-            $this->_request->setConsumerId($consumerId);
-            $route = $this->_router->match($this->_request);
-
-            if (!$this->_authorizationService->isAllowed($route->getAclResources())) {
-                throw new AuthorizationException(
-                    AuthorizationException::NOT_AUTHORIZED,
-                    ['consumer_id' => $consumerId, 'resources' => implode(', ', $route->getAclResources())]
-                );
-            }
-
+            $this->_checkPermissions();
+            $route = $this->_getCurrentRoute();
             if ($route->isSecure() && !$this->_request->isSecure()) {
                 throw new \Magento\Webapi\Exception(__('Operation allowed only in HTTPS'));
             }
@@ -178,8 +187,11 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
             $service = $this->_objectManager->get($serviceClassName);
             /** @var \Magento\Framework\Service\Data\AbstractObject $outputData */
             $outputData = call_user_func_array([$service, $serviceMethodName], $inputParams);
-            $outputArray = $this->_processServiceOutput($outputData);
-            $this->_response->prepareResponse($outputArray);
+            $outputData = $this->_processServiceOutput($outputData);
+            if ($this->_request->getParam(PartialResponseProcessor::FILTER_PARAMETER) && is_array($outputData)) {
+                $outputData = $this->partialResponseProcessor->filter($outputData);
+            }
+            $this->_response->prepareResponse($outputData);
         } catch (\Exception $e) {
             $maskedException = $this->_errorProcessor->maskException($e);
             $this->_response->setException($maskedException);
@@ -251,9 +263,72 @@ class Rest implements \Magento\Framework\App\FrontControllerInterface
     {
         foreach ($parameters as $name => $paramData) {
             if ($paramData[Converter::KEY_FORCE] || !isset($inputData[$name])) {
-                $inputData[$name] = $paramData[Converter::KEY_VALUE];
+                $value = isset($paramData['source']) && $paramData['source'] == 'session'
+                    ? $this->session->{$paramData['method']}()
+                    : $paramData[Converter::KEY_VALUE];
+                $inputData[$name] = $value;
             }
         }
         return $inputData;
     }
+
+    /**
+     * Retrieve current route.
+     *
+     * @return Route
+     */
+    protected function _getCurrentRoute()
+    {
+        if (!$this->_route) {
+            $this->_route = $this->_router->match($this->_request);
+        }
+        return $this->_route;
+    }
+
+    /**
+     * Perform authentication and authorization.
+     *
+     * Authentication can be based on active customer/guest session or it can be based on OAuth headers.
+     *
+     * @throws \Magento\Framework\Exception\AuthorizationException
+     * @return void
+     */
+    protected function _checkPermissions()
+    {
+        /**
+         * All mobile clients are expected to pass session cookie along with the request which will allow
+         * to start session automatically. User ID and user type are initialized when session is created
+         * during login call.
+         */
+        $userId = $this->session->getUserId();
+        $userType = $this->session->getUserType();
+        $userIdentifier = null;
+        $consumerId = null;
+        if ($userType) {
+            /** @var \Magento\Authz\Model\UserIdentifier $userIdentifier */
+            $userIdentifier = $this->_objectManager->create(
+                'Magento\Authz\Model\UserIdentifier',
+                ['userType' => $userType, 'userId' => $userId]
+            );
+        } else {
+            $oauthRequest = $this->_oauthHelper->prepareRequest($this->_request);
+            $consumerId = $this->_oauthService->validateAccessTokenRequest(
+                $oauthRequest,
+                $this->_oauthHelper->getRequestUrl($this->_request),
+                $this->_request->getMethod()
+            );
+            $this->_request->setConsumerId($consumerId);
+        }
+
+        $route = $this->_getCurrentRoute();
+
+        if (!$this->_authorizationService->isAllowed($route->getAclResources(), $userIdentifier)) {
+            $params = ['resources' => implode(', ', $route->getAclResources())];
+            $userParam = $consumerId
+                ? ['consumer_id' => $consumerId]
+                : ['userType' => $userType, 'userId' => $userId];
+            $params = array_merge($params, $userParam);
+            throw new AuthorizationException(AuthorizationException::NOT_AUTHORIZED, $params);
+        }
+    }
 }
diff --git a/app/code/Magento/Webapi/Controller/Rest/Response.php b/app/code/Magento/Webapi/Controller/Rest/Response.php
index a165ae92b2f..8bb1b564d5c 100644
--- a/app/code/Magento/Webapi/Controller/Rest/Response.php
+++ b/app/code/Magento/Webapi/Controller/Rest/Response.php
@@ -126,7 +126,7 @@ class Response extends \Magento\Webapi\Controller\Response
     /**
      * Perform rendering of response data.
      *
-     * @param array|null $outputData
+     * @param array|int|string|bool|float|null $outputData
      * @return $this
      */
     public function prepareResponse($outputData = null)
@@ -141,7 +141,7 @@ class Response extends \Magento\Webapi\Controller\Response
     /**
      * Render data using registered Renderer.
      *
-     * @param array|object $data
+     * @param array|int|string|bool|float|null $data
      * @return void
      */
     protected function _render($data)
diff --git a/app/code/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessor.php b/app/code/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessor.php
new file mode 100644
index 00000000000..40bb2348fb4
--- /dev/null
+++ b/app/code/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessor.php
@@ -0,0 +1,204 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright  Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Webapi\Controller\Rest\Response;
+
+use Magento\Webapi\Controller\Rest\Request as RestRequest;
+
+/**
+ * Class to handle partial service response
+ */
+class PartialResponseProcessor
+{
+    const FILTER_PARAMETER = 'fields';
+
+    /** @var RestRequest */
+    protected $_request;
+
+    /**
+     * Initialize dependencies
+     *
+     * @param RestRequest $request
+     */
+    public function __construct(RestRequest $request)
+    {
+        $this->_request = $request;
+    }
+
+    /**
+     * Process filter from the request and apply over response to get the partial results
+     *
+     * @param array $response
+     * @return array partial response array or empty array if invalid filter criteria is provided
+     */
+    public function filter($response)
+    {
+        $filter = $this->_request->getParam(self::FILTER_PARAMETER);
+        if (!is_string($filter)) {
+            return [];
+        }
+        $filterArray = $this->parse($filter);
+        if (is_null($filterArray)) {
+            return [];
+        }
+        $partialResponse = $this->applyFilter($response, $filterArray);
+        return $partialResponse;
+    }
+
+
+    /**
+     * Parse filter string into associative array. Field names are returned as keys with values for scalar fields as 1.
+     *
+     * @param string $filterString
+     * <pre>
+     *  ex. customer[id,email],addresses[city,postcode,region[region_code,region]]
+     * </pre>
+     * @return array|null
+     * <pre>
+     *  ex.
+     * array(
+     *      'customer' =>
+     *           array(
+     *               'id' => 1,
+     *               'email' => 1,
+     *               ),
+     *      'addresses' =>
+     *           array(
+     *               'city' => 1,
+     *               'postcode' => 1,
+     *                   'region' =>
+     *                       array(
+     *                           'region_code' => 1,
+     *                           'region' => 1,
+     *                         ),
+     *               ),
+     *      )
+     * </pre>
+     *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     */
+    protected function parse($filterString)
+    {
+        $length = strlen($filterString);
+        //Permissible characters in filter string: letter, number, underscore, square brackets and comma
+        if ($length == 0 || preg_match('/[^\w\[\],]+/', $filterString)) {
+            return null;
+        }
+
+        $start = null;
+        $current = [];
+        $stack = [];
+        $parent = [];
+        $currentElement = null;
+
+        for ($position = 0; $position < $length; $position++) {
+            //Extracting field when encountering field separators
+            if (in_array($filterString[$position], ['[', ']', ','])) {
+                if ($start !== null) {
+                    $currentElement = substr($filterString, $start, $position - $start);
+                    $current[$currentElement] = 1;
+                }
+                $start = null;
+            }
+            switch ($filterString[$position]) {
+                case '[':
+                    array_push($parent, $currentElement);
+                    // push current field in stack and initialize current
+                    array_push($stack, $current);
+                    $current = [];
+                    break;
+
+                case ']':
+                    //cache current
+                    $temp = $current;
+                    //Initialize with previous
+                    $current = array_pop($stack);
+                    //Add from cache
+                    $current[array_pop($parent)] = $temp;
+                    break;
+
+                //Do nothing on comma. On the next iteration field will be extracted
+                case ',':
+                    break;
+
+                default:
+                    //Move position if no field separators found
+                    if ($start === null) {
+                        $start = $position;
+                    }
+            }
+        }
+        //Check for wrongly formatted filter
+        if (!empty($stack)) {
+            return null;
+        }
+        //Check if there's any field remaining that's not added to response
+        if ($start !== null) {
+            $currentElement = substr($filterString, $start, $position - $start);
+            $current[$currentElement] = 1;
+        }
+        return $current;
+    }
+
+    /**
+     * Apply filter array
+     *
+     * @param array $responseArray
+     * @param array $filter
+     * @return array
+     */
+    protected function applyFilter(array $responseArray, array $filter)
+    {
+        $arrayIntersect = null;
+        //Check if its a sequential array. Presence of sequential arrays mean that the filed is a collection
+        //and the filtering will be applied to all the collection items
+        if (!(bool)count(array_filter(array_keys($responseArray), 'is_string'))) {
+            foreach ($responseArray as $key => &$item) {
+                $arrayIntersect[$key] = $this->recursiveArrayIntersectKey($item, $filter);
+            }
+        } else {
+            $arrayIntersect = $this->recursiveArrayIntersectKey($responseArray, $filter);
+        }
+        return $arrayIntersect;
+    }
+
+    /**
+     * Recursively compute intersection of response and filter arrays
+     *
+     * @param array $array1
+     * @param array $array2
+     * @return array
+     */
+    protected function recursiveArrayIntersectKey(array $array1, array $array2)
+    {
+        //If the field in array2 (filter) is not present in array1 (response) it will be removed after intersect
+        $arrayIntersect = array_intersect_key($array1, $array2);
+        foreach ($arrayIntersect as $key => &$value) {
+            if (is_array($value) && is_array($array2[$key])) {
+                $value = $this->applyFilter($value, $array2[$key]);
+            }
+        }
+        return $arrayIntersect;
+    }
+}
diff --git a/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Json.php b/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Json.php
index 1dbe1bc78dd..fbae2cba800 100644
--- a/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Json.php
+++ b/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Json.php
@@ -48,7 +48,7 @@ class Json implements \Magento\Webapi\Controller\Rest\Response\RendererInterface
     /**
      * Convert data to JSON.
      *
-     * @param array|object $data
+     * @param object|array|int|string|bool|float|null $data
      * @return string
      */
     public function render($data)
diff --git a/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Xml.php b/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Xml.php
index 5e2a0eae469..421905a3c07 100644
--- a/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Xml.php
+++ b/app/code/Magento/Webapi/Controller/Rest/Response/Renderer/Xml.php
@@ -68,7 +68,7 @@ class Xml implements \Magento\Webapi\Controller\Rest\Response\RendererInterface
     /**
      * Format object|array to valid XML.
      *
-     * @param array|\Magento\Framework\Object $data
+     * @param object|array|int|string|bool|float|null $data
      * @return string
      */
     public function render($data)
diff --git a/app/code/Magento/Webapi/Controller/Rest/Response/RendererInterface.php b/app/code/Magento/Webapi/Controller/Rest/Response/RendererInterface.php
index 07a63794b1f..98e730f077a 100644
--- a/app/code/Magento/Webapi/Controller/Rest/Response/RendererInterface.php
+++ b/app/code/Magento/Webapi/Controller/Rest/Response/RendererInterface.php
@@ -30,7 +30,7 @@ interface RendererInterface
     /**
      * Render content in a certain format.
      *
-     * @param array|object $data
+     * @param object|array|int|string|bool|float|null $data
      * @return string
      */
     public function render($data);
diff --git a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php
index 933ddeffc3c..8650dc1268a 100644
--- a/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php
+++ b/app/code/Magento/Webapi/Controller/Soap/Request/Handler.php
@@ -109,7 +109,15 @@ class Handler
             throw new WebapiException(__("Operation allowed only in HTTPS"));
         }
 
-        if (!$this->_authorizationService->isAllowed($serviceMethodInfo[SoapConfig::KEY_ACL_RESOURCES])) {
+        $isAllowed = false;
+        foreach ($serviceMethodInfo[SoapConfig::KEY_ACL_RESOURCES] as $resources) {
+            if ($this->_authorizationService->isAllowed($resources)) {
+                $isAllowed = true;
+                break;
+            }
+        }
+
+        if (!$isAllowed) {
             // TODO: Consider passing Integration ID instead of Consumer ID
             throw new ServiceAuthorizationException(
                 "Not Authorized.",
diff --git a/app/code/Magento/Webapi/Model/Config/Converter.php b/app/code/Magento/Webapi/Model/Config/Converter.php
index 438e35526b4..d3769681b93 100644
--- a/app/code/Magento/Webapi/Model/Config/Converter.php
+++ b/app/code/Magento/Webapi/Model/Config/Converter.php
@@ -42,6 +42,8 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
     const KEY_FORCE = 'force';
     const KEY_VALUE = 'value';
     const KEY_DATA_PARAMETERS = 'parameters';
+    const KEY_SOURCE = 'source';
+    const KEY_METHOD = 'method';
     /**#@-*/
 
     /**
@@ -67,6 +69,7 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
 
             $resources = $route->getElementsByTagName('resource');
             $resourceReferences = [];
+            $resourcePermissionSet = [];
             /** @var \DOMElement $resource */
             foreach ($resources as $resource) {
                 if ($resource->nodeType != XML_ELEMENT_NODE) {
@@ -75,8 +78,10 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
                 $ref = $resource->attributes->getNamedItem('ref')->nodeValue;
                 $resourceReferences[$ref] = true;
                 // For SOAP
-                $result[self::KEY_SERVICES][$serviceClass][$serviceMethod][self::KEY_ACL_RESOURCES][$ref] = true;
+                $resourcePermissionSet[] = $ref;
             }
+            $result[self::KEY_SERVICES][$serviceClass][$serviceMethod][self::KEY_ACL_RESOURCES][]
+                = $resourcePermissionSet;
 
             $parameters = $route->getElementsByTagName('parameter');
             $data = [];
@@ -93,6 +98,14 @@ class Converter implements \Magento\Framework\Config\ConverterInterface
                     self::KEY_FORCE => $force,
                     self::KEY_VALUE => ($value === 'null') ? null : $value,
                 ];
+                $sourceNode = $parameter->attributes->getNamedItem('source');
+                if ($sourceNode) {
+                    $data[$name][self::KEY_SOURCE] = $sourceNode->nodeValue;
+                }
+                $methodNode = $parameter->attributes->getNamedItem('method');
+                if ($methodNode) {
+                    $data[$name][self::KEY_METHOD] = $methodNode->nodeValue;
+                }
             }
 
             $method = $route->attributes->getNamedItem('method')->nodeValue;
diff --git a/app/code/Magento/Webapi/Model/Plugin/AuthorizationServiceV1.php b/app/code/Magento/Webapi/Model/Plugin/AuthorizationServiceV1.php
index eba5c1f758e..4ec91252cfc 100644
--- a/app/code/Magento/Webapi/Model/Plugin/AuthorizationServiceV1.php
+++ b/app/code/Magento/Webapi/Model/Plugin/AuthorizationServiceV1.php
@@ -24,7 +24,7 @@
 namespace Magento\Webapi\Model\Plugin;
 
 use Magento\Authz\Model\UserIdentifier;
-use Magento\Integration\Service\IntegrationV1 as IntegrationService;
+use Magento\Integration\Service\V1\Integration as IntegrationService;
 use Magento\Integration\Model\Integration;
 use Magento\Framework\Logger;
 
diff --git a/app/code/Magento/Webapi/Model/Plugin/IntegrationServiceV1.php b/app/code/Magento/Webapi/Model/Plugin/IntegrationServiceV1.php
index 6aea72599a6..45b2de646e8 100644
--- a/app/code/Magento/Webapi/Model/Plugin/IntegrationServiceV1.php
+++ b/app/code/Magento/Webapi/Model/Plugin/IntegrationServiceV1.php
@@ -29,7 +29,7 @@ use Magento\Integration\Model\Integration as IntegrationModel;
 use Magento\Authz\Service\AuthorizationV1Interface as AuthorizationInterface;
 
 /**
- * Plugin for \Magento\Integration\Service\IntegrationV1.
+ * Plugin for \Magento\Integration\Service\V1\Integration.
  */
 class IntegrationServiceV1
 {
@@ -54,13 +54,13 @@ class IntegrationServiceV1
     /**
      * Persist API permissions.
      *
-     * @param \Magento\Integration\Service\IntegrationV1 $subject
+     * @param \Magento\Integration\Service\V1\Integration $subject
      * @param IntegrationModel $integration
      *
      * @return IntegrationModel
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function afterCreate(\Magento\Integration\Service\IntegrationV1 $subject, $integration)
+    public function afterCreate(\Magento\Integration\Service\V1\Integration $subject, $integration)
     {
         $this->_saveApiPermissions($integration);
         return $integration;
@@ -69,13 +69,13 @@ class IntegrationServiceV1
     /**
      * Persist API permissions.
      *
-     * @param \Magento\Integration\Service\IntegrationV1 $subject
+     * @param \Magento\Integration\Service\V1\Integration $subject
      * @param IntegrationModel $integration
      *
      * @return IntegrationModel
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function afterUpdate(\Magento\Integration\Service\IntegrationV1 $subject, $integration)
+    public function afterUpdate(\Magento\Integration\Service\V1\Integration $subject, $integration)
     {
         $this->_saveApiPermissions($integration);
         return $integration;
@@ -84,13 +84,13 @@ class IntegrationServiceV1
     /**
      * Add API permissions to integration data.
      *
-     * @param \Magento\Integration\Service\IntegrationV1 $subject
+     * @param \Magento\Integration\Service\V1\Integration $subject
      * @param IntegrationModel $integration
      *
      * @return IntegrationModel
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function afterGet(\Magento\Integration\Service\IntegrationV1 $subject, $integration)
+    public function afterGet(\Magento\Integration\Service\V1\Integration $subject, $integration)
     {
         $this->_addAllowedResources($integration);
         return $integration;
@@ -151,13 +151,13 @@ class IntegrationServiceV1
     /**
      * Process integration resource permissions after the integration is created
      *
-     * @param \Magento\Integration\Service\IntegrationV1 $subject
+     * @param \Magento\Integration\Service\V1\Integration $subject
      * @param array $integrationData Data of integration deleted
      *
      * @return array $integrationData
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function afterDelete(\Magento\Integration\Service\IntegrationV1 $subject, array $integrationData)
+    public function afterDelete(\Magento\Integration\Service\V1\Integration $subject, array $integrationData)
     {
         //No check needed for integration data since it cannot be empty in the parent invocation - delete
         $userIdentifier = $this->_userIdentifierFactory->create(
diff --git a/app/code/Magento/Webapi/Model/Plugin/Setup.php b/app/code/Magento/Webapi/Model/Plugin/Setup.php
index 13525a8c616..aa7ce338185 100644
--- a/app/code/Magento/Webapi/Model/Plugin/Setup.php
+++ b/app/code/Magento/Webapi/Model/Plugin/Setup.php
@@ -43,7 +43,7 @@ class Setup
     /**
      * Integration service
      *
-     * @var \Magento\Integration\Service\IntegrationV1Interface
+     * @var \Magento\Integration\Service\V1\IntegrationInterface
      */
     protected $_integrationService;
 
@@ -66,13 +66,13 @@ class Setup
      *
      * @param IntegrationConfig $integrationConfig
      * @param \Magento\Authz\Service\AuthorizationV1 $authzService
-     * @param \Magento\Integration\Service\IntegrationV1Interface $integrationService
+     * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService
      * @param \Magento\Authz\Model\UserIdentifier\Factory $userIdentifierFactory
      */
     public function __construct(
         IntegrationConfig $integrationConfig,
         \Magento\Authz\Service\AuthorizationV1 $authzService,
-        \Magento\Integration\Service\IntegrationV1Interface $integrationService,
+        \Magento\Integration\Service\V1\IntegrationInterface $integrationService,
         \Magento\Authz\Model\UserIdentifier\Factory $userIdentifierFactory
     ) {
         $this->_integrationConfig = $integrationConfig;
diff --git a/app/code/Magento/Webapi/Model/Soap/Config.php b/app/code/Magento/Webapi/Model/Soap/Config.php
index c9abded2381..2857b810b61 100644
--- a/app/code/Magento/Webapi/Model/Soap/Config.php
+++ b/app/code/Magento/Webapi/Model/Soap/Config.php
@@ -155,7 +155,7 @@ class Config
                         self::KEY_METHOD => $methodName,
                         self::KEY_IS_REQUIRED => (bool)$methodMetadata[Converter::KEY_SECURE],
                         self::KEY_IS_SECURE => $methodMetadata[Converter::KEY_SECURE],
-                        self::KEY_ACL_RESOURCES => array_keys($methodMetadata[Converter::KEY_ACL_RESOURCES]),
+                        self::KEY_ACL_RESOURCES => $methodMetadata[Converter::KEY_ACL_RESOURCES],
                     ];
                     $this->_soapServices[$serviceName][self::KEY_CLASS] = $serviceClass;
                 }
diff --git a/app/code/Magento/Webapi/etc/di.xml b/app/code/Magento/Webapi/etc/di.xml
index 7cc770692bc..d62d987b602 100644
--- a/app/code/Magento/Webapi/etc/di.xml
+++ b/app/code/Magento/Webapi/etc/di.xml
@@ -40,7 +40,29 @@
     <type name="Magento\Framework\Xml\Parser" shared="false" />
     <type name="Magento\Framework\Code\Scanner\DirectoryScanner" shared="false" />
     <type name="Magento\Server\Reflection" shared="false" />
-    <type name="Magento\Integration\Service\IntegrationV1">
+    <type name="Magento\Integration\Service\V1\Integration">
         <plugin name="webapiIntegrationServiceV1" type="Magento\Webapi\Model\Plugin\IntegrationServiceV1"/>
     </type>
+    <type name="Magento\Webapi\Controller\Rest\Request\Deserializer\Factory">
+        <arguments>
+            <argument name="deserializers" xsi:type="array">
+                <item name="application_json" xsi:type="array">
+                    <item name="type" xsi:type="string">application/json</item>
+                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Json</item>
+                </item>
+                <item name="application_xml" xsi:type="array">
+                    <item name="type" xsi:type="string">application/xml</item>
+                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
+                </item>
+                <item name="application_xhtml_xml" xsi:type="array">
+                    <item name="type" xsi:type="string">application/xhtml+xml</item>
+                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
+                </item>
+                <item name="text_xml" xsi:type="array">
+                    <item name="type" xsi:type="string">text/xml</item>
+                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
+                </item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/GroupedProduct/etc/import.xml b/app/code/Magento/Webapi/etc/frontend/routes.xml
similarity index 80%
rename from app/code/Magento/GroupedProduct/etc/import.xml
rename to app/code/Magento/Webapi/etc/frontend/routes.xml
index d066db9e0d7..aaf9f104676 100644
--- a/app/code/Magento/GroupedProduct/etc/import.xml
+++ b/app/code/Magento/Webapi/etc/frontend/routes.xml
@@ -23,6 +23,10 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/import.xsd">
-    <productType name="grouped" model="Magento\GroupedProduct\Model\Import\Entity\Product\Type\Grouped" />
+<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="api" frontName="api">
+            <module name="Magento_Webapi" />
+        </route>
+    </router>
 </config>
diff --git a/app/code/Magento/Webapi/etc/module.xml b/app/code/Magento/Webapi/etc/module.xml
index 0b17a6de534..45b9ec4ab39 100644
--- a/app/code/Magento/Webapi/etc/module.xml
+++ b/app/code/Magento/Webapi/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Webapi" version="1.0.0.4" active="true">
+    <module name="Magento_Webapi" schema_version="1.0.0.4" active="true">
         <sequence>
             <module name="Magento_Core"/>
             <module name="Magento_Store"/>
@@ -38,6 +38,7 @@
             <module name="Magento_Backend"/>
             <module name="Magento_User"/>
             <module name="Magento_Authz"/>
+            <module name="Magento_Customer"/>
         </depends>
     </module>
 </config>
diff --git a/app/code/Magento/Webapi/etc/webapi.xsd b/app/code/Magento/Webapi/etc/webapi.xsd
index 0d17ba34279..9770ae30c07 100644
--- a/app/code/Magento/Webapi/etc/webapi.xsd
+++ b/app/code/Magento/Webapi/etc/webapi.xsd
@@ -69,7 +69,7 @@
        <xs:attribute name="ref" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:string">
-                   <xs:pattern value=".+::.+(, ?.+::.+)*"/>
+                   <xs:pattern value=".+(, ?.+)*"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
@@ -86,6 +86,8 @@
             <xs:extension base="xs:string">
                 <xs:attribute name="name" type="xs:string" use="required"/>
                 <xs:attribute name="force" type="xs:boolean"/>
+                <xs:attribute name="source" type="xs:string"/>
+                <xs:attribute name="method" type="xs:string"/>
             </xs:extension>
         </xs:simpleContent>
     </xs:complexType>
diff --git a/app/code/Magento/Webapi/etc/webapi_rest/di.xml b/app/code/Magento/Webapi/etc/webapi_rest/di.xml
index 1c3a3896a04..82dbff2c61a 100644
--- a/app/code/Magento/Webapi/etc/webapi_rest/di.xml
+++ b/app/code/Magento/Webapi/etc/webapi_rest/di.xml
@@ -33,28 +33,6 @@
     <preference for="Magento\Framework\App\FrontControllerInterface" type="Magento\Webapi\Controller\Rest" />
     <preference for="Magento\Framework\Model\ActionValidator\RemoveAction" type="Magento\Framework\Model\ActionValidator\RemoveAction\Allowed" />
     <type name="Magento\Webapi\Controller\Rest\Router\Route" shared="false" />
-    <type name="Magento\Webapi\Controller\Rest\Request\Deserializer\Factory">
-        <arguments>
-            <argument name="deserializers" xsi:type="array">
-                <item name="application_json" xsi:type="array">
-                    <item name="type" xsi:type="string">application/json</item>
-                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Json</item>
-                </item>
-                <item name="application_xml" xsi:type="array">
-                    <item name="type" xsi:type="string">application/xml</item>
-                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
-                </item>
-                <item name="application_xhtml_xml" xsi:type="array">
-                    <item name="type" xsi:type="string">application/xhtml+xml</item>
-                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
-                </item>
-                <item name="text_xml" xsi:type="array">
-                    <item name="type" xsi:type="string">text/xml</item>
-                    <item name="model" xsi:type="string">Magento\Webapi\Controller\Rest\Request\Deserializer\Xml</item>
-                </item>
-            </argument>
-        </arguments>
-    </type>
     <type name="Magento\Webapi\Controller\Rest\Response\Renderer\Factory">
         <arguments>
             <argument name="renders" xsi:type="array">
@@ -93,4 +71,9 @@
     <type name="Magento\Authz\Service\AuthorizationV1">
         <plugin name="webapiRestAuthorizationV1" type="Magento\Webapi\Model\Plugin\AuthorizationServiceV1" />
     </type>
+    <type name="Magento\Framework\Session\Generic">
+        <arguments>
+            <argument name="sessionName" xsi:type="string">frontend</argument>
+        </arguments>
+    </type>
 </config>
diff --git a/app/code/Magento/Weee/etc/module.xml b/app/code/Magento/Weee/etc/module.xml
index b2aa4af66ad..5b9ce1ed900 100644
--- a/app/code/Magento/Weee/etc/module.xml
+++ b/app/code/Magento/Weee/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Weee" version="1.6.0.0" active="true">
+    <module name="Magento_Weee" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Catalog"/>
             <module name="Magento_Tax"/>
diff --git a/app/code/Magento/Widget/etc/module.xml b/app/code/Magento/Widget/etc/module.xml
index b1880423c64..ddbc1e300fa 100644
--- a/app/code/Magento/Widget/etc/module.xml
+++ b/app/code/Magento/Widget/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Widget" version="1.6.0.2" active="true">
+    <module name="Magento_Widget" schema_version="1.6.0.2" active="true">
         <sequence>
             <module name="Magento_Cms"/>
         </sequence>
diff --git a/app/code/Magento/Wishlist/etc/module.xml b/app/code/Magento/Wishlist/etc/module.xml
index 78fb20dd85a..fbf025e1362 100644
--- a/app/code/Magento/Wishlist/etc/module.xml
+++ b/app/code/Magento/Wishlist/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Wishlist" version="1.6.0.0" active="true">
+    <module name="Magento_Wishlist" schema_version="1.6.0.0" active="true">
         <sequence>
             <module name="Magento_Customer"/>
             <module name="Magento_Catalog"/>
diff --git a/app/design/adminhtml/Magento/backend/Magento_Theme/web/css/source/module.less b/app/design/adminhtml/Magento/backend/Magento_Theme/web/css/source/module.less
index 3f8ddff06b0..98e9e939692 100644
--- a/app/design/adminhtml/Magento/backend/Magento_Theme/web/css/source/module.less
+++ b/app/design/adminhtml/Magento/backend/Magento_Theme/web/css/source/module.less
@@ -535,6 +535,29 @@ button {
     }
 }
 
+//
+// Icons
+//--------------------------------------
+.icon-error {
+  margin-left: 15px;
+  color: #c00815;
+  font-size: 11px;
+  &:before {
+    font-family: 'MUI-Icons';
+    content: "\e086";
+    font-size: 13px;
+    line-height: 13px;
+    overflow: hidden;
+    speak: none;
+    font-weight: normal;
+    -webkit-font-smoothing: antialiased;
+    display: inline-block;
+    vertical-align: middle;
+    text-align: center;
+    margin: -1px 5px 0 0;
+  }
+}
+
 .ui-widget-overlay {
     position: fixed;
 }
diff --git a/app/design/adminhtml/Magento/backend/theme.xml b/app/design/adminhtml/Magento/backend/theme.xml
index accbe0e9020..c06a36c1457 100644
--- a/app/design/adminhtml/Magento/backend/theme.xml
+++ b/app/design/adminhtml/Magento/backend/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Magento 2 backend</title>
-    <version>1.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/app/design/frontend/Magento/blank/theme.xml b/app/design/frontend/Magento/blank/theme.xml
index 15abef70d14..5aaed7f208c 100644
--- a/app/design/frontend/Magento/blank/theme.xml
+++ b/app/design/frontend/Magento/blank/theme.xml
@@ -24,7 +24,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Magento Blank</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <media>
         <preview_image>media/preview.jpg</preview_image>
     </media>
diff --git a/app/design/frontend/Magento/plushe/theme.xml b/app/design/frontend/Magento/plushe/theme.xml
index 9d6e99bd163..8514bf3b331 100644
--- a/app/design/frontend/Magento/plushe/theme.xml
+++ b/app/design/frontend/Magento/plushe/theme.xml
@@ -24,7 +24,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Magento Plushe</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>Magento/blank</parent>
     <media>
         <preview_image>media/preview.jpg</preview_image>
diff --git a/app/design/install/Magento/basic/theme.xml b/app/design/install/Magento/basic/theme.xml
index a16406212d9..fbb0258f6c0 100644
--- a/app/design/install/Magento/basic/theme.xml
+++ b/app/design/install/Magento/basic/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Magento Basic</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/custom/hierarchy_config.xml b/app/i18n/Magento/de_DE/language.xml
similarity index 80%
rename from dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/custom/hierarchy_config.xml
rename to app/i18n/Magento/de_DE/language.xml
index 03fdb9e6614..1c019d56b85 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/custom/hierarchy_config.xml
+++ b/app/i18n/Magento/de_DE/language.xml
@@ -23,5 +23,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config>
-</config>
\ No newline at end of file
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>de_DE</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/default/hierarchy_config.xml b/app/i18n/Magento/en_US/language.xml
similarity index 80%
rename from dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/default/hierarchy_config.xml
rename to app/i18n/Magento/en_US/language.xml
index 03fdb9e6614..4f7b0310a0a 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/_files/default/hierarchy_config.xml
+++ b/app/i18n/Magento/en_US/language.xml
@@ -23,5 +23,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config>
-</config>
\ No newline at end of file
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>en_US</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/app/i18n/Magento/es_ES/language.xml b/app/i18n/Magento/es_ES/language.xml
new file mode 100644
index 00000000000..f0466320b88
--- /dev/null
+++ b/app/i18n/Magento/es_ES/language.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>es_ES</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/app/i18n/Magento/fr_FR/language.xml b/app/i18n/Magento/fr_FR/language.xml
new file mode 100644
index 00000000000..461fdf7a05d
--- /dev/null
+++ b/app/i18n/Magento/fr_FR/language.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>fr_FR</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/app/i18n/Magento/nl_NL/language.xml b/app/i18n/Magento/nl_NL/language.xml
new file mode 100644
index 00000000000..99fbfee22d8
--- /dev/null
+++ b/app/i18n/Magento/nl_NL/language.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>nl_NL</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/app/i18n/Magento/pt_BR/language.xml b/app/i18n/Magento/pt_BR/language.xml
new file mode 100644
index 00000000000..401fc7016a5
--- /dev/null
+++ b/app/i18n/Magento/pt_BR/language.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>pt_BR</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/app/i18n/Magento/zh_CN/language.xml b/app/i18n/Magento/zh_CN/language.xml
new file mode 100644
index 00000000000..af174e14d44
--- /dev/null
+++ b/app/i18n/Magento/zh_CN/language.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>zh_CN</code>
+    <vendor>Magento</vendor>
+</language>
diff --git a/dev/tests/functional/bootstrap.php b/dev/tests/functional/bootstrap.php
index 9b6926f79a1..61b94c8a78c 100644
--- a/dev/tests/functional/bootstrap.php
+++ b/dev/tests/functional/bootstrap.php
@@ -23,6 +23,7 @@
  */
 
 session_start();
+defined('MTF_BOOT_FILE') || define('MTF_BOOT_FILE', __FILE__);
 require_once __DIR__ . '/../../../app/bootstrap.php';
 restore_error_handler();
 require_once __DIR__ . '/vendor/autoload.php';
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectgrouplistElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectgrouplistElement.php
index f205f6e3d45..da34098763d 100644
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectgrouplistElement.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectgrouplistElement.php
@@ -211,6 +211,7 @@ class MultiselectgrouplistElement extends MultiselectElement
      * Get value
      *
      * @return array
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function getValue()
     {
diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/Tree.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/Tree.php
index 03e11557086..541f99156d0 100644
--- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/Tree.php
+++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/Tree.php
@@ -67,6 +67,7 @@ abstract class Tree extends Element
      *
      * @param ElementInterface $target
      * @throws \BadMethodCallException
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function dragAndDrop(ElementInterface $target)
     {
@@ -82,7 +83,6 @@ abstract class Tree extends Element
     public function getValue()
     {
         throw new \BadMethodCallException('Not applicable for this class of elements (TreeElement)');
-
     }
 
     /**
@@ -91,6 +91,7 @@ abstract class Tree extends Element
      *
      * @param array $keys
      * @throws \BadMethodCallException
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function keys(array $keys)
     {
diff --git a/dev/tests/functional/lib/Mtf/ObjectManagerFactory.php b/dev/tests/functional/lib/Mtf/ObjectManagerFactory.php
index b28f9bda7e3..f73acbfd63e 100644
--- a/dev/tests/functional/lib/Mtf/ObjectManagerFactory.php
+++ b/dev/tests/functional/lib/Mtf/ObjectManagerFactory.php
@@ -33,6 +33,7 @@ use Magento\Framework\ObjectManager as MagentoObjectManager;
  * Class ObjectManagerFactory
  *
  * @api
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class ObjectManagerFactory
 {
@@ -77,7 +78,10 @@ class ObjectManagerFactory
         $directories = isset($arguments[\Magento\Framework\App\Filesystem::PARAM_APP_DIRS])
             ? $arguments[\Magento\Framework\App\Filesystem::PARAM_APP_DIRS]
             : array();
-        $directoryList = new \Magento\Framework\App\Filesystem\DirectoryList(realpath(MTF_BP . '../../../../'), $directories);
+        $directoryList = new \Magento\Framework\App\Filesystem\DirectoryList(
+            realpath(MTF_BP . '../../../../'),
+            $directories
+        );
         (new \Magento\Framework\Autoload\IncludePath())->addIncludePath(
             array($directoryList->getDir(\Magento\Framework\App\Filesystem::GENERATION_DIR))
         );
@@ -104,8 +108,10 @@ class ObjectManagerFactory
      * @param array $arguments
      * @return \Magento\Framework\App\Arguments
      */
-    protected function createAppArguments(\Magento\Framework\App\Filesystem\DirectoryList $directoryList, array $arguments)
-    {
+    protected function createAppArguments(
+        \Magento\Framework\App\Filesystem\DirectoryList $directoryList,
+        array $arguments
+    ) {
         return new \Magento\Framework\App\Arguments(
             $arguments,
             new \Magento\Framework\App\Arguments\Loader(
diff --git a/dev/tests/functional/lib/Mtf/Page/BackendPage.php b/dev/tests/functional/lib/Mtf/Page/BackendPage.php
index b05f6f79e89..eee04decfd5 100644
--- a/dev/tests/functional/lib/Mtf/Page/BackendPage.php
+++ b/dev/tests/functional/lib/Mtf/Page/BackendPage.php
@@ -28,6 +28,7 @@ use Mtf\Factory\Factory;
 /**
  * Class BackendPage
  *
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 class BackendPage extends Page
 {
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 cbb0daf7bc2..f3a9202afce 100644
--- a/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php
+++ b/dev/tests/functional/lib/Mtf/Util/Generate/Factory/AbstractFactory.php
@@ -153,6 +153,7 @@ abstract class AbstractFactory
      *
      * @param string $type
      * @return array
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     protected function collectItems($type)
     {
@@ -203,6 +204,7 @@ abstract class AbstractFactory
      * @param string $location
      * @param string $path
      * @throws \Exception
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     protected function _processItem(& $items, & $rewrites, $filename, $location, $path)
     {
@@ -218,7 +220,7 @@ abstract class AbstractFactory
         }
         $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations($className);
 
-        list($fullLocationPath, $targetClassName) = explode($location . '/', $filename);
+        list(, $targetClassName) = explode($location . '/', $filename);
         $targetClassName = str_replace('.php', '', $targetClassName);
         $targetClassName = str_replace('/', '\\', $targetClassName);
 
diff --git a/dev/tests/functional/lib/Mtf/Util/Generate/Repository/Resource.php b/dev/tests/functional/lib/Mtf/Util/Generate/Repository/Resource.php
index 3e01f290e0b..60dccf467eb 100644
--- a/dev/tests/functional/lib/Mtf/Util/Generate/Repository/Resource.php
+++ b/dev/tests/functional/lib/Mtf/Util/Generate/Repository/Resource.php
@@ -47,6 +47,7 @@ class Resource extends \Magento\Framework\Model\Resource\Db\AbstractDb
      * @param mixed $value
      * @param null $field
      * @return \Magento\Framework\Model\Resource\Db\AbstractDb|void
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
     {
diff --git a/dev/tests/functional/lib/Mtf/Util/Generate/TestCase.php b/dev/tests/functional/lib/Mtf/Util/Generate/TestCase.php
index a8e8a87495f..264557871c3 100644
--- a/dev/tests/functional/lib/Mtf/Util/Generate/TestCase.php
+++ b/dev/tests/functional/lib/Mtf/Util/Generate/TestCase.php
@@ -98,6 +98,7 @@ class TestCase extends AbstractGenerate
      *
      * @return array
      * @throws \Exception
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     protected function getTicketData($jiraTicket)
     {
@@ -179,6 +180,8 @@ class TestCase extends AbstractGenerate
      *
      * @param \SimpleXMLElement $item
      * @return void
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     private function generateTestCaseClass(\SimpleXMLElement $item)
     {
diff --git a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlInterface.php b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlInterface.php
index 8e0a84a841d..af0bc70bd04 100644
--- a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlInterface.php
+++ b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlInterface.php
@@ -50,11 +50,11 @@ interface CurlInterface
      *
      * @param string $method
      * @param string $url
-     * @param string $http_ver
+     * @param string $httpVer
      * @param array  $headers
      * @param array  $params
      */
-    public function write($method, $url, $http_ver = '1.1', $headers = array(), $params = array());
+    public function write($method, $url, $httpVer = '1.1', $headers = array(), $params = array());
 
     /**
      * Read response from server
diff --git a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport.php b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport.php
index 3fd787b6b22..a7dcb3990f8 100644
--- a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport.php
+++ b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport.php
@@ -70,6 +70,8 @@ class CurlTransport implements CurlInterface
      * Apply current configuration array to curl resource
      *
      * @return $this
+     *
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
      */
     protected function _applyConfig()
     {
@@ -131,11 +133,11 @@ class CurlTransport implements CurlInterface
      *
      * @param $method
      * @param $url
-     * @param string $http_ver
+     * @param string $httpVer
      * @param array $headers
      * @param array $params
      */
-    public function write($method, $url, $http_ver = '1.1', $headers = array(), $params = array())
+    public function write($method, $url, $httpVer = '1.1', $headers = array(), $params = array())
     {
         $this->_applyConfig();
         $options = array(
@@ -260,12 +262,12 @@ class CurlTransport implements CurlInterface
     /**
      * Extract the response code from a response string
      *
-     * @param string $response_str
+     * @param string $responseStr
      * @return int
      */
-    public static function extractCode($response_str)
+    public static function extractCode($responseStr)
     {
-        preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
+        preg_match("|^HTTP/[\d\.x]+ (\d+)|", $responseStr, $m);
 
         if (isset($m[1])) {
             return (int)$m[1];
diff --git a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
index 97520bdade6..f1569c68c78 100644
--- a/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
+++ b/dev/tests/functional/lib/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php
@@ -101,20 +101,20 @@ class BackendDecorator implements CurlInterface
      *
      * @param string $method
      * @param string $url
-     * @param string $http_ver
+     * @param string $httpVer
      * @param array $headers
      * @param array $params
      *
      * @throws \Exception
      */
-    public function write($method, $url, $http_ver = '1.1', $headers = array(), $params = array())
+    public function write($method, $url, $httpVer = '1.1', $headers = array(), $params = array())
     {
         if ($this->_formKey) {
             $params['form_key'] = $this->_formKey;
         } else {
             throw new \Exception('Form key is absent! Response: '. $this->_response);
         }
-        $this->_transport->write($method, $url, $http_ver, $headers, http_build_query($params));
+        $this->_transport->write($method, $url, $httpVer, $headers, http_build_query($params));
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Form.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Form.php
index 8b891509ff1..ec1bfc0801e 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Form.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Form.php
@@ -136,6 +136,8 @@ class Form extends FormInstance
      *
      * @param FixtureInterface $fixture
      * @return Form
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function save(FixtureInterface $fixture = null)
     {
@@ -185,6 +187,8 @@ class Form extends FormInstance
      *
      * @param FixtureInterface $fixture
      * @return Form
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function delete(FixtureInterface $fixture = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/FormTabs.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/FormTabs.php
index f8c59b083ea..3d78145b1fc 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/FormTabs.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/FormTabs.php
@@ -36,6 +36,8 @@ use Mtf\Fixture\InjectableFixture;
 /**
  * Class FormTabs
  * Is used to represent any form with tabs on the page
+ *
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 class FormTabs extends Form
 {
@@ -162,6 +164,8 @@ class FormTabs extends Form
      *
      * @param array $tabs
      * @throws \Exception
+     *
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
      */
     protected function fillMissedFields(array $tabs)
     {
@@ -189,6 +193,9 @@ class FormTabs extends Form
      * @param FixtureInterface|null $fixture
      * @param Element|null $element
      * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData(FixtureInterface $fixture = null, Element $element = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php
index 2a7b67f0d4e..c2c6e9fad22 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php
@@ -32,6 +32,8 @@ use Mtf\Client\Element\Locator;
 /**
  * Abstract class Grid
  * Basic grid actions
+ *
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 abstract class Grid extends Block
 {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Tab.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Tab.php
index 5fe1995edfc..5ae5f4ed6af 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Tab.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Tab.php
@@ -30,6 +30,8 @@ use Mtf\Block\Form as AbstractForm;
 /**
  * Class Tab
  * Is used to represent any tab on the page
+ *
+ * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 class Tab extends AbstractForm
 {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Date.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Date.php
index 5186e8a1752..5a9080880c6 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Date.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Fixture/Date.php
@@ -82,6 +82,8 @@ class Date implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Ui/LogoutUser.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Ui/LogoutUser.php
index 113499a50ba..10a606c4f9e 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Ui/LogoutUser.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Ui/LogoutUser.php
@@ -41,6 +41,8 @@ class LogoutUser extends Ui
      *
      * @param FixtureInterface $fixture [optional]
      * @return mixed|string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function persist(FixtureInterface $fixture = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
index c1b300dfbf7..e7305ce2070 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php
@@ -129,6 +129,8 @@ class Option extends Block
      * @param array $fields
      * @param Element $context
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function fillBundleOption(array $fields, Element $context)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Price.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Price.php
index 70621d1b994..b6f7c8faf76 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Price.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Price.php
@@ -77,6 +77,8 @@ class Price implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Selections.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Selections.php
index 263b636b478..bbd9539f78a 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Selections.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Bundle/Selections.php
@@ -102,6 +102,8 @@ class Selections implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
@@ -153,6 +155,7 @@ class Selections implements FixtureInterface
      * @param $name
      * @return mixed
      * @throws \InvalidArgumentException
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function getPreset($name)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
index 9633ad2e9f9..77172bed75d 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/BundleFixed.php
@@ -34,6 +34,8 @@ class BundleFixed extends Bundle
 {
     /**
      * Initialize fixture data
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function _initData()
     {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
index ff1f13a2449..3419fa0d584 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/CatalogProductBundle.php
@@ -33,6 +33,9 @@ use Mtf\System\Event\EventManagerInterface;
 
 /**
  * Class CatalogProductBundle
+ *
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductBundle extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
index 61f37ad3122..1f00d14261b 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/CatalogProductBundle.php
@@ -32,6 +32,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class CatalogProductBundle extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['BundleDynamic_sku_1073507449'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/AffectedAttributeSetForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/AffectedAttributeSetForm.php
index 56526dd15e6..1ada4332728 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/AffectedAttributeSetForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/AffectedAttributeSetForm.php
@@ -40,7 +40,8 @@ class AffectedAttributeSetForm extends ParentForm
      *
      * @var string
      */
-    protected $confirmButton = '//parent::div[div[@id="affected-attribute-set-form"]]//button[contains(@id,"confirm-button")]';
+    protected $confirmButton =
+        '//parent::div[div[@id="affected-attribute-set-form"]]//button[contains(@id,"confirm-button")]';
 
     /**
      * Locator buttons new name attribute set
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
index 2bb98bc26af..4e544bc808e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php
@@ -31,6 +31,8 @@ use Mtf\Client\Element\Locator;
 /**
  * Class Custom Options
  * Block of custom options product
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  */
 class CustomOptions extends Block
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
index 5313e5ccb79..a38fb787091 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Search.php
@@ -80,6 +80,8 @@ class Search extends Block
      *
      * @param string $keyword
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.ConstructorWithNameAsEnclosingClass)
      */
     public function search($keyword)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
index 7fe6cdba788..cf84ebe3663 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductForm.php
@@ -125,6 +125,8 @@ class AssertProductForm extends AbstractConstraint
      * @param array $fixtureData
      * @param array $formData
      * @return array
+     *
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     protected function compareArray(array $fixtureData, array $formData)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
index f9af209aced..c4b0f4ebd13 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogCategory.php
@@ -29,6 +29,8 @@ use Mtf\Fixture\InjectableFixture;
 /**
  * Class CatalogCategory
  * Category fixture
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogCategory extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.php
index 246c8d68b02..442b6ce020e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute.php
@@ -28,6 +28,8 @@ use Mtf\Fixture\InjectableFixture;
 
 /**
  * Class CatalogAttributeEntity
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductAttribute extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute/Options.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute/Options.php
index b87fdb5c5c9..680588a7960 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute/Options.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductAttribute/Options.php
@@ -60,6 +60,8 @@ class Options implements FixtureInterface
      *
      * @param string|null $key
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
index 117ebb65743..571664c4286 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.php
@@ -34,6 +34,9 @@ use Mtf\System\Event\EventManagerInterface;
 /**
  * Class CatalogProductSimple
  * Product Simple fixture
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
  */
 class CatalogProductSimple extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
index be1ec366fad..a8b463e1fdf 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CategoryIds.php
@@ -103,6 +103,8 @@ class CategoryIds implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
index 3750cbc12c7..b5b1a060b1b 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomOptions.php
@@ -68,6 +68,8 @@ class CustomOptions implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
@@ -87,6 +89,8 @@ class CustomOptions implements FixtureInterface
     /**
      * @param string $name
      * @return array|null
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function getPreset($name)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
index 0964f7e4330..361228f31e6 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/GroupPriceOptions.php
@@ -69,6 +69,8 @@ class GroupPriceOptions implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
index 19d881b7ad2..aef5c617c10 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php
@@ -84,6 +84,8 @@ class Price implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
index 2e6869e5425..1783fb091d4 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TaxClass.php
@@ -88,6 +88,8 @@ class TaxClass implements FixtureInterface
      *
      * @param string|null $key
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
index 34445ea841f..f0e1d290c2e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/TierPriceOptions.php
@@ -63,6 +63,8 @@ class TierPriceOptions implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
index 71f159d6ea1..9b6c364cd58 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductVirtual.php
@@ -33,6 +33,9 @@ use Mtf\System\Event\EventManagerInterface;
 
 /**
  * Class CatalogProductVirtual
+ *
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductVirtual extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
index 56971d1ac26..7a0b5247763 100755
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ConfigurableProduct.php
@@ -204,6 +204,8 @@ class ConfigurableProduct extends Product
      * Init Data
      *
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function _initData()
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ProductAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ProductAttribute.php
index c88362c23b5..96c3edb4b72 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ProductAttribute.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/ProductAttribute.php
@@ -120,6 +120,8 @@ class ProductAttribute extends DataFixture
 
     /**
      * {inheritdoc}
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
      */
     protected function _initData()
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
index e503bd54504..1d918e0302d 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductSimple/Curl.php
@@ -83,6 +83,9 @@ class Curl extends AbstractCurl implements CatalogProductSimpleInterface
      * @param FixtureInterface $fixture [optional]
      * @return array
      * @throws \Exception
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      */
     public function persist(FixtureInterface $fixture = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProduct.php
index 055689e2b39..b0e993350d7 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProduct.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/Curl/CreateProduct.php
@@ -101,6 +101,8 @@ class CreateProduct extends Curl
      * @param FixtureInterface $fixture [optional]
      * @return mixed|string
      * @throws \Exception
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function persist(FixtureInterface $fixture = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategory.php
index 0184cbca19b..e9c2fa3a1b1 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategory.php
@@ -80,6 +80,8 @@ class CatalogCategory extends Page
      *
      * @param array $params
      * @return $this
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function open(array $params = array())
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryEdit.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryEdit.php
index ddfbd0b2ded..f4e8a13b1bd 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryEdit.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Category/CatalogCategoryEdit.php
@@ -88,6 +88,8 @@ class CatalogCategoryEdit extends Page
      *
      * @param array $params
      * @return $this
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function open(array $params = array())
     {
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
index 7cf65ab2382..fb472f7134a 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogCategory.php
@@ -32,6 +32,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class CatalogCategory extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['default_subcategory'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
index 2fa30e1e301..97603f853fd 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.php
@@ -32,6 +32,13 @@ use Mtf\Repository\AbstractRepository;
  */
 class CatalogProductSimple extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['default'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/EditSimpleProductTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/EditSimpleProductTest.php
index e9fb1f95036..33f0b3d5859 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/EditSimpleProductTest.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/EditSimpleProductTest.php
@@ -110,7 +110,6 @@ class EditSimpleProductTest extends Functional
         //Pages
         $frontendHomePage = Factory::getPageFactory()->getCmsIndexIndex();
         $categoryPage = Factory::getPageFactory()->getCatalogCategoryView();
-        $productPage = Factory::getPageFactory()->getCatalogProductView();
         //Steps
         $frontendHomePage->open();
         $frontendHomePage->getTopmenu()->selectCategoryByName($categoryName);
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
index 3d1f9eedeca..2df7b25a35b 100644
--- 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
@@ -74,6 +74,8 @@ class SearchData implements FixtureInterface
      *
      * @param string|null $key
      * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
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 01898df2aa9..5e2861cf2fc 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
@@ -87,6 +87,8 @@ class AdvancedSearchEntityTest extends Injectable
      * @param CmsIndex $cmsIndex
      * @param AdvancedSearch $searchPage
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function testSearch(
         array $products,
diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php
index f111082b687..55d49a779f8 100644
--- a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php
+++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php
@@ -31,5 +31,5 @@ use Mtf\Handler\HandlerInterface;
  */
 interface CmsPageInterface extends HandlerInterface
 {
-   //
+    //
 }
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
index 4c36a7a6884..9911c1543b1 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable.php
@@ -34,6 +34,8 @@ use Mtf\System\Event\EventManagerInterface;
 /**
  * Class CatalogProductConfigurable
  *
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductConfigurable extends InjectableFixture
 {
@@ -45,7 +47,9 @@ class CatalogProductConfigurable extends InjectableFixture
     /**
      * @var string
      */
-    protected $handlerInterface = 'Magento\ConfigurableProduct\Test\Handler\CatalogProductConfigurable\CatalogProductConfigurableInterface';
+    protected $handlerInterface =
+        'Magento\ConfigurableProduct\Test\Handler\CatalogProductConfigurable\CatalogProductConfigurableInterface';
+
     /**
      * Constructor
      *
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/AttributeOptions.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/AttributeOptions.php
index 5f5fe255ef3..5000b9504b9 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/AttributeOptions.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/AttributeOptions.php
@@ -69,6 +69,8 @@ class AttributeOptions implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableOptions.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableOptions.php
index ad12ca332e4..3522a77313e 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableOptions.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/ConfigurableOptions.php
@@ -69,6 +69,8 @@ class ConfigurableOptions implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/Price.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/Price.php
index e3d76576df5..b8c21146c70 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/Price.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/CatalogProductConfigurable/Price.php
@@ -77,6 +77,8 @@ class Price implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/CatalogProductConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/CatalogProductConfigurable.php
index 10ed462496d..d455dc52296 100644
--- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/CatalogProductConfigurable.php
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/CatalogProductConfigurable.php
@@ -32,6 +32,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class CatalogProductConfigurable extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['default'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
index c9881283b0c..c48c17d14c4 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Form/Login.php
@@ -53,6 +53,8 @@ class Login extends Form
      * Login customer in the Frontend
      *
      * @param FixtureInterface $customer
+     *
+     * @SuppressWarnings(PHPMD.ConstructorWithNameAsEnclosingClass)
      */
     public function login(FixtureInterface $customer)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInGrid.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInGrid.php
index dc229c13a61..8b02c27f3d9 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInGrid.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInGrid.php
@@ -48,6 +48,8 @@ class AssertCustomerInGrid extends AbstractConstraint
      * @param CustomerIndex $pageCustomerIndex
      * @param CustomerInjectable $initialCustomer [optional]
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.NPathComplexity)
      */
     public function processAssert(
         CustomerInjectable $customer,
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressInjectable.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressInjectable.php
index 4a0a8a94968..2186040256b 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/AddressInjectable.php
@@ -28,6 +28,8 @@ use Mtf\Fixture\InjectableFixture;
 
 /**
  * Class AddressInjectable
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class AddressInjectable extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroup/TaxClassIds.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroup/TaxClassIds.php
index 838822246a2..2919f8f2149 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroup/TaxClassIds.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerGroup/TaxClassIds.php
@@ -73,6 +73,8 @@ class TaxClassIds implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
index cbeb35f7767..e493d886dd1 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Fixture/CustomerInjectable.php
@@ -29,6 +29,8 @@ use Mtf\Fixture\InjectableFixture;
 /**
  * Class CustomerInjectable
  * Customer fixture
+ *
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CustomerInjectable extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
index 52c1ff5f295..9c271b32400 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerInjectable.php
@@ -36,6 +36,8 @@ class CustomerInjectable extends AbstractRepository
     /**
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
index e54ea692f01..3f79f35d3c1 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable.php
@@ -34,6 +34,9 @@ use Mtf\System\Event\EventManagerInterface;
 /**
  * Class CatalogProductDownloadable
  * Fixture for Downloadable product
+ *
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class CatalogProductDownloadable extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Links.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Links.php
index 0fdcb311173..fc54c753055 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Links.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Links.php
@@ -62,6 +62,8 @@ class Links implements FixtureInterface
      *
      * @param string $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Samples.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Samples.php
index cff42de45c7..b060900fa40 100644
--- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Samples.php
+++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/CatalogProductDownloadable/Samples.php
@@ -62,6 +62,8 @@ class Samples implements FixtureInterface
      *
      * @param string $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php b/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php
index 4141b11447d..5b249be324f 100644
--- a/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php
+++ b/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php
@@ -36,6 +36,8 @@ class Rating extends AbstractRepository
      * @constructor
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Repository/Sitemap.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Repository/Sitemap.php
index b65b83749bd..1e8aeb34f69 100644
--- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Repository/Sitemap.php
+++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Repository/Sitemap.php
@@ -32,6 +32,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class Sitemap extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['default'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php
index ed71e7fa850..15416a4c8fc 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php
@@ -128,6 +128,8 @@ class Form extends FormInterface
      * @param FixtureInterface $fixture
      * @param Element $element
      * @return $this|void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function fill(FixtureInterface $fixture, Element $element = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php
index e6871d46fe9..03455840c0d 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleApplying.php
@@ -108,6 +108,8 @@ abstract class AssertTaxRuleApplying extends AbstractConstraint
      * @param array $shipping
      * @param TaxRule $initialTaxRule
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function processAssert(
         FixtureFactory $fixtureFactory,
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxClass.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxClass.php
index 4c52c1b111d..eb508ef9b9c 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxClass.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxClass.php
@@ -85,6 +85,8 @@ class TaxClass implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxRate.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxRate.php
index fbbbb82f917..168bf53910f 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxRate.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Fixture/TaxRule/TaxRate.php
@@ -85,6 +85,8 @@ class TaxRate implements FixtureInterface
      *
      * @param $key [optional]
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/Curl/RemoveTaxRule.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/Curl/RemoveTaxRule.php
index be9630835e6..6ff58cdadab 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/Curl/RemoveTaxRule.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/Curl/RemoveTaxRule.php
@@ -52,6 +52,8 @@ class RemoveTaxRule extends Curl
      *
      * @param FixtureInterface $fixture [optional]
      * @return mixed|string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function persist(FixtureInterface $fixture = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
index b3d25e63fde..808748546a8 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxClass/Curl.php
@@ -66,10 +66,10 @@ class Curl extends AbstractCurl implements TaxClassInterface
      */
     protected function getClassId($response)
     {
-        $data = json_decode($response);
-        if ($data->success !== true) {
+        $data = json_decode($response, true);
+        if ($data['success'] !== true) {
             throw new \Exception("Tax class creation by curl handler was not successful! Response: $response");
         }
-        return isset($data->class_id) ? (int)$data->class_id : null;
+        return isset($data['class_id']) ? (int)$data['class_id'] : null;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
index d76a231d294..c612e198ecc 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRate/Curl.php
@@ -94,10 +94,10 @@ class Curl extends AbstractCurl implements TaxRateInterface
      */
     protected function getTaxRateId($response)
     {
-        $data = json_decode($response);
-        if ($data->success !== true) {
+        $data = json_decode($response, true);
+        if ($data['success'] !== true) {
             throw new \Exception("Tax rate creation by curl handler was not successful! Response: $response");
         }
-        return isset($data->tax_calculation_rate_id) ? (int)$data->tax_calculation_rate_id : null;
+        return isset($data['tax_calculation_rate_id']) ? (int)$data['tax_calculation_rate_id'] : null;
     }
 }
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
index 0779ad699ec..77e5da858c9 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Handler/TaxRule/Curl.php
@@ -74,6 +74,8 @@ class Curl extends AbstractCurl implements TaxRuleInterface
      *
      * @param FixtureInterface $fixture
      * @return mixed
+     *
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
      */
     protected function prepareData($fixture)
     {
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.php
index 57bf7d25d79..73b584adcdd 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.php
@@ -31,6 +31,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class TaxClass extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['Taxable Goods'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
index 7f220dafe5c..79f847e4fba 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.php
@@ -28,9 +28,17 @@ use Mtf\Repository\AbstractRepository;
 
 /**
  * Class TaxRate Repository
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  */
 class TaxRate extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['US-CA-*-Rate 1'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
index 00ad6fa0e5f..5e6b4807ce9 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.php
@@ -31,6 +31,12 @@ use Mtf\Repository\AbstractRepository;
  */
 class TaxRule extends AbstractRepository
 {
+    /**
+     * @param array $defaultConfig
+     * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
         $this->_data['custom_rule'] = [
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRuleEntityTest.php
index 46a92ba977d..2197c1e5896 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRuleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRuleEntityTest.php
@@ -98,6 +98,8 @@ class DeleteTaxRuleEntityTest extends Injectable
      * @param TaxRule $taxRule
      * @param AddressInjectable $address
      * @param array $shipping
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function testDeleteTaxRule(
         TaxRule $taxRule,
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRuleEntityTest.php
index 41008abe979..d35d8a55467 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRuleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRuleEntityTest.php
@@ -103,6 +103,8 @@ class UpdateTaxRuleEntityTest extends Injectable
      * @param AddressInjectable $address
      * @param array $shipping
      * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function testUpdateTaxRule(
         TaxRule $initialTaxRule,
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
index d67d9cc7dc0..ac2d8b7d434 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php
@@ -86,6 +86,8 @@ class IdPath implements FixtureInterface
      *
      * @param string|null $key
      * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getData($key = null)
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
index 0d461528f1a..e6cc865008a 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewrite.php
@@ -35,6 +35,8 @@ class UrlRewrite extends AbstractRepository
     /**
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
index 94b4f009759..fa7d0c40ee3 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteCategory.php
@@ -36,6 +36,8 @@ class UrlRewriteCategory extends AbstractRepository
     /**
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = array(), array $defaultData = array())
     {
diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
index bb08f2cb0da..355014c69b5 100644
--- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
+++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Repository/UrlRewriteProduct.php
@@ -36,6 +36,8 @@ class UrlRewriteProduct extends AbstractRepository
     /**
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = array(), array $defaultData = array())
     {
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/LoginSuccess.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/LoginSuccess.php
index e0f73c3b6fc..50f10eead4d 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/LoginSuccess.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/LoginSuccess.php
@@ -45,6 +45,8 @@ class LoginSuccess extends AbstractConstraint
      *
      * @param AdminUserInjectable $fixture
      * @param Dashboard $dashboard
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function processAssert(AdminUserInjectable $fixture, Dashboard $dashboard)
     {
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/AdminUserInjectable.php b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/AdminUserInjectable.php
index 0c6dd05ad1f..d767dbd0d8e 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Fixture/AdminUserInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Fixture/AdminUserInjectable.php
@@ -29,6 +29,7 @@ use Mtf\Fixture\InjectableFixture;
 /**
  * Class AdminUserInjectable
  *
+ * @SuppressWarnings(PHPMD.TooManyFields)
  */
 class AdminUserInjectable extends InjectableFixture
 {
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserInjectable.php b/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserInjectable.php
index feeccc7cd5c..d1d6d809c4c 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserInjectable.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserInjectable.php
@@ -35,6 +35,8 @@ class AdminUserInjectable extends AbstractRepository
      * @constructor
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserRole.php b/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserRole.php
index c50b52232b9..c1da04d4f5f 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserRole.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Repository/AdminUserRole.php
@@ -35,6 +35,8 @@ class AdminUserRole extends AbstractRepository
      * @constructor
      * @param array $defaultConfig
      * @param array $defaultData
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct(array $defaultConfig = [], array $defaultData = [])
     {
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
index 97cc5a45aa7..f7d092739fb 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteAdminUserEntityTest.php
@@ -80,12 +80,12 @@ class DeleteAdminUserEntityTest extends Injectable
     {
         $role = $fixtureFactory->createByCode('adminUserRole', ['dataSet' => 'default']);
         $role->persist();
-        $role_id = $role->getData('role_id');
+        $roleId = $role->getData('role_id');
         $adminUser = $fixtureFactory->createByCode(
             'adminUserInjectable',
             [
                 'dataSet' => 'custom_admin',
-                'data' => ['role_id' => $role_id]
+                'data' => ['role_id' => $roleId]
             ]
         );
         $adminUser->persist();
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteUserRoleEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteUserRoleEntityTest.php
index 292b155242f..cfbbe6a88de 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteUserRoleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/DeleteUserRoleEntityTest.php
@@ -80,12 +80,12 @@ class DeleteUserRoleEntityTest extends Injectable
     {
         $role = $fixtureFactory->createByCode('adminUserRole', ['dataSet' => 'default']);
         $role->persist();
-        $role_id = $role->getData('role_id');
+        $roleId = $role->getData('role_id');
         $adminUser = $fixtureFactory->createByCode(
             'adminUserInjectable',
             [
                 'dataSet' => 'custom_admin',
-                'data' => ['role_id' => $role_id]
+                'data' => ['role_id' => $roleId]
             ]
         );
         $adminUser->persist();
diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests.php b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests.php
index 86af6f4492a..9dcd1a1ef17 100644
--- a/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests.php
+++ b/dev/tests/functional/testsuites/Mtf/TestSuite/InjectableTests.php
@@ -59,6 +59,8 @@ class InjectableTests extends \PHPUnit_Framework_TestSuite
      * @param bool $processIsolation
      *
      * @return \PHPUnit_Framework_TestResult|void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function run(
         \PHPUnit_Framework_TestResult $result = null,
diff --git a/dev/tests/integration/testsuite/Magento/Backend/Model/Search/CatalogTest.php b/dev/tests/integration/testsuite/Magento/Backend/Model/Search/CatalogTest.php
new file mode 100644
index 00000000000..56fa09f348c
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Backend/Model/Search/CatalogTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Backend\Model\Search;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * @magentoAppArea adminhtml
+ */
+class CatalogTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Backend\Model\Search\Catalog */
+    protected $catalogSearch;
+
+    protected function setUp()
+    {
+        $this->catalogSearch = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+            ->create('\Magento\Backend\Model\Search\Catalog');
+    }
+
+    /**
+     * Dataprovider for testLoad
+     */
+    public function dataProviderForTestLoad()
+    {
+        return [
+            ['StoreTitle', true], // positive case
+            ['Some other', false], // negative case
+        ];
+    }
+
+    /**
+     * Check that we can find product by name from previous
+     *
+     * @dataProvider dataProviderForTestLoad
+     * @magentoDbIsolation enabled
+     * @magentoDataFixture Magento/Catalog/_files/product_simple_multistore.php
+     */
+    public function testLoad($viewName, $expectedResult)
+    {
+        $results = $this->catalogSearch->setStart(0)
+            ->setLimit(20)
+            ->setQuery($viewName)
+            ->load()
+            ->getResults();
+        $result = false;
+        $product = array_shift($results);
+        if ($product
+            && $product['type'] == 'Product'
+            && $product['name'] == 'Simple Product One'
+        ) {
+            $result = true;
+        }
+        $this->assertEquals(
+            $expectedResult,
+            $result,
+            'Can\'t find product "Simple Product One" with name "StoreTitle" on second store view'
+        );
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/DesignTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/DesignTest.php
index e000164f6b1..8dd23a0fb00 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/DesignTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/DesignTest.php
@@ -76,7 +76,7 @@ class DesignTest extends \PHPUnit_Framework_TestCase
             'theme_code' => 'theme',
             'package_code' => 'package',
             'theme_path' => 'package/theme',
-            'theme_version' => '2.0.0.0',
+            'theme_version' => '0.1.0',
             'parent_theme' => null,
             'is_featured' => true,
             'preview_image' => '',
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
similarity index 94%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
index e4b6a849501..d7536203fd4 100644
--- a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
@@ -21,12 +21,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity;
+namespace Magento\CatalogImportExport\Model\Export;
 
 class ProductTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\ImportExport\Model\Export\Entity\Product
+     * @var \Magento\CatalogImportExport\Model\Export\Product
      */
     protected $_model;
 
@@ -63,7 +63,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         parent::setUp();
 
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            'Magento\ImportExport\Model\Export\Entity\Product'
+            'Magento\CatalogImportExport\Model\Export\Product'
         );
     }
 
@@ -83,7 +83,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     /**
      * Verify that all stock item attribute values are exported (aren't equal to empty string)
      *
-     * @covers \Magento\ImportExport\Model\Export\Entity\Product::export
+     * @covers \Magento\CatalogImportExport\Model\Export\Product::export
      * @magentoDataFixture Magento/ImportExport/_files/product.php
      */
     public function testExportStockItemAttributesAreFilled()
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php
similarity index 96%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractTest.php
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php
index 70ab77b1984..abb620ebd15 100644
--- a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php
@@ -21,12 +21,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product\Type;
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 class AbstractTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType
+     * @var \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
      */
     protected $_model;
 
@@ -37,9 +37,9 @@ class AbstractTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $params = array($objectManager->create('Magento\ImportExport\Model\Import\Entity\Product'), 'simple');
+        $params = array($objectManager->create('Magento\CatalogImportExport\Model\Import\Product'), 'simple');
         $this->_model = $this->getMockForAbstractClass(
-            'Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType',
+            'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType',
             array(
                 $objectManager->get('Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory'),
                 $objectManager->get('Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory'),
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
similarity index 97%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index 605e24bff73..4d95deec498 100644
--- a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -23,12 +23,12 @@
  */
 
 /**
- * Test class for \Magento\ImportExport\Model\Import\Entity\Product
+ * Test class for \Magento\CatalogImportExport\Model\Import\Product
  *
  * The "CouplingBetweenObjects" warning is caused by tremendous complexity of the original class
  *
  */
-namespace Magento\ImportExport\Model\Import\Entity;
+namespace Magento\CatalogImportExport\Model\Import;
 
 /**
  * Class ProductTest
@@ -38,31 +38,31 @@ namespace Magento\ImportExport\Model\Import\Entity;
 class ProductTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\ImportExport\Model\Import\Entity\Product
+     * @var \Magento\CatalogImportExport\Model\Import\Product
      */
     protected $_model;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Uploader
+     * @var \Magento\CatalogImportExport\Model\Import\Uploader
      */
     protected $_uploader;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\UploaderFactory
+     * @var \Magento\CatalogImportExport\Model\Import\UploaderFactory
      */
     protected $_uploaderFactory;
 
     protected function setUp()
     {
         $this->_uploaderFactory = $this->getMock(
-            'Magento\ImportExport\Model\Import\UploaderFactory',
+            'Magento\CatalogImportExport\Model\Import\UploaderFactory',
             array('create'),
             array(),
             '',
             false
         );
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            'Magento\ImportExport\Model\Import\Entity\Product',
+            'Magento\CatalogImportExport\Model\Import\Product',
             array('uploaderFactory' => $this->_uploaderFactory)
         );
     }
@@ -327,7 +327,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
             if (!empty($data['_custom_option_row_title']) && empty($data['_custom_option_store'])) {
                 $optionData = array();
                 foreach ($this->_assertOptionValues as $assertKey) {
-                    $valueKey = \Magento\ImportExport\Model\Import\Entity\Product\Option::COLUMN_PREFIX .
+                    $valueKey = \Magento\CatalogImportExport\Model\Import\Product\Option::COLUMN_PREFIX .
                         'row_' .
                         $assertKey;
                     $optionData[$assertKey] = $data[$valueKey];
@@ -539,7 +539,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
 
         $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         $uploader = $this->getMock(
-            'Magento\ImportExport\Model\Import\Uploader',
+            'Magento\CatalogImportExport\Model\Import\Uploader',
             array('init'),
             array(
                 $objectManager->create('Magento\Core\Helper\File\Storage\Database'),
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/product_with_custom_options.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/product_with_custom_options.csv
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import.csv
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import_invalid_attribute_set.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import_invalid_attribute_set.csv
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import_with_datetime.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_datetime.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/ImportExport/Model/Import/Entity/_files/products_to_import_with_datetime.csv
rename to dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_datetime.csv
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/Resource/Theme/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Core/Model/Resource/Theme/CollectionTest.php
index 58e401bb1b7..b57c83183d6 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/Resource/Theme/CollectionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/Resource/Theme/CollectionTest.php
@@ -264,7 +264,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test/default',
                 'code' => 'test/default',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Test',
                 'preview_image' => 'test_default.jpg',
                 'is_featured' => '1',
@@ -275,7 +275,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test/pro',
                 'code' => 'test/pro',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Professional Test',
                 'preview_image' => 'test_default.jpg',
                 'is_featured' => '1',
@@ -286,7 +286,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test/fixed1',
                 'code' => 'test/fixed1',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Theme test 1',
                 'preview_image' => 'test_default.jpg',
                 'is_featured' => '1',
@@ -297,7 +297,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test/fixed2',
                 'code' => 'test/fixed2',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Theme test 2',
                 'preview_image' => 'test_default.jpg',
                 'is_featured' => '1',
@@ -308,7 +308,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test/fixed3',
                 'code' => 'test/fixed3',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Theme test 3',
                 'preview_image' => 'test_default.jpg',
                 'is_featured' => '1',
@@ -328,7 +328,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => '0',
                 'theme_path' => 'test1/test1',
                 'code' => 'test1/test1',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Test1',
                 'preview_image' => 'test1_test1.jpg',
                 'is_featured' => '1',
@@ -339,7 +339,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => 'area51/test1/test1',
                 'theme_path' => 'test1/test2',
                 'code' => 'test1/test2',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Test2',
                 'preview_image' => 'test1_test2.jpg',
                 'is_featured' => '1',
@@ -350,7 +350,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => 'area51/test1/test2',
                 'theme_path' => 'test1/test3',
                 'code' => 'test1/test3',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Test3',
                 'preview_image' => 'test1_test3.jpg',
                 'is_featured' => '1',
@@ -361,7 +361,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'parent_id' => 'area51/test1/test0',
                 'theme_path' => 'test1/test4',
                 'code' => 'test1/test4',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'theme_title' => 'Test4',
                 'preview_image' => 'test1_test4.jpg',
                 'is_featured' => '1',
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/Theme/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Core/Model/Theme/CollectionTest.php
index 50781a37024..03fc64e9744 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/Theme/CollectionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/Theme/CollectionTest.php
@@ -93,7 +93,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
                 'expectedData' => array(
                     'area' => 'frontend',
                     'theme_title' => 'Default',
-                    'theme_version' => '2.0.0.0',
+                    'theme_version' => '0.1.0',
                     'parent_id' => null,
                     'parent_theme_path' => null,
                     'theme_path' => 'magento_default',
@@ -122,7 +122,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
             array(
                 'area' => 'space_area',
                 'theme_title' => 'Space theme',
-                'theme_version' => '2.0.0.0',
+                'theme_version' => '0.1.0',
                 'parent_id' => null,
                 'is_featured' => false,
                 'theme_path' => 'default_space',
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/Theme/Domain/VirtualTest.php b/dev/tests/integration/testsuite/Magento/Core/Model/Theme/Domain/VirtualTest.php
index 9c22ba2ce30..c8717f9dee5 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/Theme/Domain/VirtualTest.php
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/Theme/Domain/VirtualTest.php
@@ -34,7 +34,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase
         'physical' => array(
             'parent_id' => null,
             'theme_path' => 'test/test',
-            'theme_version' => '1.0.0.0',
+            'theme_version' => '0.1.0',
             'theme_title' => 'Test physical theme',
             'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
             'type' => ThemeInterface::TYPE_PHYSICAL
@@ -42,7 +42,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase
         'virtual' => array(
             'parent_id' => null,
             'theme_path' => '',
-            'theme_version' => '1.0.0.0',
+            'theme_version' => '0.1.0',
             'theme_title' => 'Test virtual theme',
             'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
             'type' => ThemeInterface::TYPE_VIRTUAL
@@ -50,7 +50,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase
         'staging' => array(
             'parent_id' => null,
             'theme_path' => '',
-            'theme_version' => '1.0.0.0',
+            'theme_version' => '0.1.0',
             'theme_title' => 'Test staging theme',
             'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
             'type' => ThemeInterface::TYPE_STAGING
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/ThemeTest.php b/dev/tests/integration/testsuite/Magento/Core/Model/ThemeTest.php
index 1c7a7095f9e..606fe403cf4 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/ThemeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/ThemeTest.php
@@ -38,7 +38,7 @@ class ThemeTest extends \PHPUnit_Framework_TestCase
         );
         $themeModel->setData($this->_getThemeValidData());
 
-        $crud = new \Magento\TestFramework\Entity($themeModel, array('theme_version' => '2.0.0.1'));
+        $crud = new \Magento\TestFramework\Entity($themeModel, array('theme_version' => '0.1.0'));
         $crud->testCrud();
     }
 
@@ -52,7 +52,7 @@ class ThemeTest extends \PHPUnit_Framework_TestCase
         return array(
             'area' => 'space_area',
             'theme_title' => 'Space theme',
-            'theme_version' => '2.0.0.0',
+            'theme_version' => '0.1.0',
             'parent_id' => null,
             'is_featured' => false,
             'theme_path' => 'default/space',
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/adminhtml/vendor_test/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/adminhtml/vendor_test/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/adminhtml/vendor_test/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/adminhtml/vendor_test/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/area_two/vendor_theme_one/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/area_two/vendor_theme_one/theme.xml
index 3b4844f8a80..6d909ef24c4 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/area_two/vendor_theme_one/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/area_two/vendor_theme_one/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Theme One</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/design_area/vendor_theme_one/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/design_area/vendor_theme_one/theme.xml
index 3b4844f8a80..6d909ef24c4 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/design_area/vendor_theme_one/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/design_area/vendor_theme_one/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Theme One</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default_iphone/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default_iphone/theme.xml
index 354d902229a..afdec08f307 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default_iphone/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/magento_default_iphone/theme.xml
@@ -24,7 +24,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Iphone</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>magento_default</parent>
     <media>
         <preview_image>images/preview_image.jpg</preview_image>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_cache_test_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_cache_test_theme/theme.xml
index 283b844eac5..d14054d687c 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_cache_test_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_cache_test_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Cache Test Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>test_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_default/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_publication/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_publication/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_publication/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_publication/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_test_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_test_theme/theme.xml
index 7ed14377826..95aeb417cbd 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_test_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/test_test_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>test_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_custom_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_custom_theme/theme.xml
index 7d000c2185f..3ba75a6f380 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_custom_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_custom_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Custom Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>vendor_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_default/theme.xml b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/Model/_files/design/frontend/vendor_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/_files/etc/module.xml b/dev/tests/integration/testsuite/Magento/Core/_files/etc/module.xml
index d8d9626360f..f278e548b1d 100644
--- a/dev/tests/integration/testsuite/Magento/Core/_files/etc/module.xml
+++ b/dev/tests/integration/testsuite/Magento/Core/_files/etc/module.xml
@@ -24,5 +24,5 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Core" version="1.6.0.2" />
+    <module name="Magento_Core" schema_version="1.6.0.2" />
 </config>
diff --git a/dev/tests/integration/testsuite/Magento/Core/_files/layout_update.php b/dev/tests/integration/testsuite/Magento/Core/_files/layout_update.php
index aa5afec21c0..3a87e66dd9b 100644
--- a/dev/tests/integration/testsuite/Magento/Core/_files/layout_update.php
+++ b/dev/tests/integration/testsuite/Magento/Core/_files/layout_update.php
@@ -32,7 +32,7 @@ $theme = $objectManager->create('Magento\Framework\View\Design\ThemeInterface');
 $theme->setThemePath(
     'test/test'
 )->setThemeVersion(
-    '2.0.0.0'
+    '0.1.0'
 )->setArea(
     'frontend'
 )->setThemeTitle(
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/SessionTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/SessionTest.php
index 2f8df00304c..596be6d18af 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/SessionTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Model/SessionTest.php
@@ -44,13 +44,9 @@ class SessionTest extends \PHPUnit_Framework_TestCase
 
     public function testLoginById()
     {
-        $this->markTestSkipped('MAGETWO-18328');
-        $oldSessionId = $this->_customerSession->getSessionId();
         $this->assertTrue($this->_customerSession->loginById(1));
         // fixture
         $this->assertTrue($this->_customerSession->isLoggedIn());
-        $newSessionId = $this->_customerSession->getSessionId();
-        $this->assertNotEquals($oldSessionId, $newSessionId);
     }
 
     /**
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php b/dev/tests/integration/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
index fd36e4dfd62..c4a41810b75 100755
--- a/dev/tests/integration/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
+++ b/dev/tests/integration/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
@@ -1338,7 +1338,7 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     *
+     * @magentoAppArea adminhtml
      * @magentoDataFixture Magento/Customer/_files/customer.php
      * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
      * @expectedException \Magento\Framework\Exception\NoSuchEntityException
@@ -1346,7 +1346,6 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
      */
     public function testDeleteCustomerWithAddress()
     {
-        $this->markTestSkipped('MAGETWO-22014');
         //Verify address is created for the customer;
         $result = $this->_customerAddressService->getAddresses(1);
         $this->assertEquals(2, count($result));
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
similarity index 97%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
index 1a268106220..c4e5f27ade9 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
-use Magento\Customer\Model\ImportExport\Import\Address as ImportAddress;
+use Magento\CustomerImportExport\Model\Import\Address as ImportAddress;
 /**
  * Test for customer address export model
  *
@@ -47,7 +47,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     {
         parent::setUp();
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            'Magento\Customer\Model\ImportExport\Export\Address'
+            'Magento\CustomerImportExport\Model\Export\Address'
         );
 
         $websites = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
similarity index 97%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
index 2d2332f77bf..6db81937cd7 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
@@ -25,19 +25,19 @@
 /**
  * Test for customer export model
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
 class CustomerTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Customer\Model\ImportExport\Export\Customer
+     * @var \Magento\CustomerImportExport\Model\Export\Customer
      */
     protected $_model;
 
     protected function setUp()
     {
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
-            'Magento\Customer\Model\ImportExport\Export\Customer'
+            'Magento\CustomerImportExport\Model\Export\Customer'
         );
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
similarity index 99%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
index 22c34b08204..ccd5242e48b 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
@@ -23,9 +23,9 @@
  */
 
 /**
- * Test class for \Magento\Customer\Model\ImportExport\Import\Address
+ * Test class for \Magento\CustomerImportExport\Model\Import\Address
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class AddressTest extends \PHPUnit_Framework_TestCase
 {
@@ -34,7 +34,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
      *
      * @var string
      */
-    protected $_testClassName = 'Magento\Customer\Model\ImportExport\Import\Address';
+    protected $_testClassName = 'Magento\CustomerImportExport\Model\Import\Address';
 
     /**
      * Fixture key from fixture
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
similarity index 98%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
index 30db707aa67..accd9b15f33 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
 {
@@ -98,7 +98,7 @@ class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
     {
         $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
         $this->_entityAdapter = $this->_objectManager->create(
-            'Magento\Customer\Model\ImportExport\Import\CustomerComposite'
+            'Magento\CustomerImportExport\Model\Import\CustomerComposite'
         );
     }
 
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
similarity index 97%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
index 89e83aee6f5..de5c454cb7a 100644
--- a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
@@ -21,12 +21,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 use Magento\ImportExport\Model\Import;
 
 /**
- * Test for class \Magento\Customer\Model\ImportExport\Import\Customer which covers validation logic
+ * Test for class \Magento\CustomerImportExport\Model\Import\Customer which covers validation logic
  */
 class CustomerTest extends \PHPUnit_Framework_TestCase
 {
@@ -57,7 +57,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
         parent::setUp();
 
         $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->create('Magento\Customer\Model\ImportExport\Import\Customer');
+            ->create('Magento\CustomerImportExport\Model\Import\Customer');
         $this->_model->setParameters(['behavior' => Import::BEHAVIOR_ADD_UPDATE]);
 
         $propertyAccessor = new \ReflectionProperty($this->_model, '_messageTemplates');
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/address_import_delete.csv b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/address_import_delete.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/address_import_delete.csv
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/address_import_delete.csv
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/address_import_update.csv b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/address_import_update.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/address_import_update.csv
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/address_import_update.csv
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_delete.csv b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_delete.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_delete.csv
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_delete.csv
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_update.csv b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_update.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_update.csv
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_update.csv
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customers_to_import.csv b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customers_to_import.csv
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customers_to_import.csv
rename to dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/_files/customers_to_import.csv
diff --git a/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test/theme.xml b/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test_child/theme.xml b/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test_child/theme.xml
index bb1b22e3591..009b2dcee99 100644
--- a/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test_child/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/DesignEditor/Model/_files/design/frontend/vendor_test_child/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default Child</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>vendor_test</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/DesignEditor/_files/design_editor_active.php b/dev/tests/integration/testsuite/Magento/DesignEditor/_files/design_editor_active.php
index 920aadb881b..04e61f79bbf 100644
--- a/dev/tests/integration/testsuite/Magento/DesignEditor/_files/design_editor_active.php
+++ b/dev/tests/integration/testsuite/Magento/DesignEditor/_files/design_editor_active.php
@@ -43,7 +43,7 @@ $theme->setData(
         'area' => 'frontend',
         'parent_id' => null,
         'theme_path' => 'Magento/blank',
-        'theme_version' => '2.0.0.0',
+        'theme_version' => '0.1.0',
         'theme_title' => 'Default',
         'preview_image' => 'media/preview_image.jpg',
         'is_featured' => '0'
diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/adminhtml/test_default/theme.xml b/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/adminhtml/test_default/theme.xml
index 873b3a74610..44ae187382c 100644
--- a/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/adminhtml/test_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/adminhtml/test_default/theme.xml
@@ -25,5 +25,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/frontend/test_default/theme.xml b/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/frontend/test_default/theme.xml
index 873b3a74610..44ae187382c 100644
--- a/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/frontend/test_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Email/Model/_files/design/frontend/test_default/theme.xml
@@ -25,5 +25,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Core/Helper/AbstractTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Helper/AbstractHelperTest.php
similarity index 92%
rename from dev/tests/integration/testsuite/Magento/Core/Helper/AbstractTest.php
rename to dev/tests/integration/testsuite/Magento/Framework/App/Helper/AbstractHelperTest.php
index c20e7b86d99..41528830040 100644
--- a/dev/tests/integration/testsuite/Magento/Core/Helper/AbstractTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/App/Helper/AbstractHelperTest.php
@@ -21,12 +21,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Core\Helper;
+namespace Magento\Framework\App\Helper;
 
-class AbstractTest extends \PHPUnit_Framework_TestCase
+class AbstractHelperTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Framework\App\Helper\AbstractHelper|PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Framework\App\Helper\AbstractHelper|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $_helper = null;
 
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_default/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_default/theme.xml
index 70c12935365..d91d3468248 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_default/theme.xml
@@ -25,6 +25,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>test_parent</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_parent/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_parent/theme.xml
index 59e678505be..a60ef913e54 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_parent/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/Less/_files/design/frontend/test_parent/theme.xml
@@ -25,5 +25,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test Parent</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Object/Copy/Config/_files/Magento/Test/etc/module.xml b/dev/tests/integration/testsuite/Magento/Framework/Object/Copy/Config/_files/Magento/Test/etc/module.xml
index 63aa7da0ace..ee1d7873ab8 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Object/Copy/Config/_files/Magento/Test/etc/module.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/Object/Copy/Config/_files/Magento/Test/etc/module.xml
@@ -24,5 +24,5 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Test" version="1.11.0.1" active="true" />
+    <module name="Magento_Test" schema_version="1.11.0.1" active="true" />
 </config>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Design/Theme/ValidatorTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Design/Theme/ValidatorTest.php
index 03989cbccc0..e35a2fa4922 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/Design/Theme/ValidatorTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/Design/Theme/ValidatorTest.php
@@ -83,7 +83,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase
         return array(
             'theme_code' => 'space',
             'theme_title' => 'Space theme',
-            'theme_version' => '2.0.0.0',
+            'theme_version' => '0.1.0',
             'parent_theme' => null,
             'theme_path' => 'default/space',
             'preview_image' => 'images/preview.png'
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/adminhtml/vendor_test/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/adminhtml/vendor_test/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/adminhtml/vendor_test/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/adminhtml/vendor_test/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/area_two/vendor_theme_one/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/area_two/vendor_theme_one/theme.xml
index 3b4844f8a80..6d909ef24c4 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/area_two/vendor_theme_one/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/area_two/vendor_theme_one/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Theme One</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/design_area/vendor_theme_one/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/design_area/vendor_theme_one/theme.xml
index 3b4844f8a80..6d909ef24c4 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/design_area/vendor_theme_one/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/design_area/vendor_theme_one/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Theme One</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default_iphone/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default_iphone/theme.xml
index 97412435086..d7299034efd 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default_iphone/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/magento_default_iphone/theme.xml
@@ -24,7 +24,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Iphone</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>magento_default</parent>
     <media>
         <preview_image>images/preview.png</preview_image>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_cache_test_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_cache_test_theme/theme.xml
index 283b844eac5..d14054d687c 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_cache_test_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_cache_test_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Cache Test Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>test_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_default/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_publication/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_publication/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_publication/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_publication/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_test_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_test_theme/theme.xml
index 7ed14377826..95aeb417cbd 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_test_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/test_test_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>test_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_custom_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_custom_theme/theme.xml
index 7d000c2185f..3ba75a6f380 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_custom_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_custom_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Custom Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>vendor_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_default/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_default/theme.xml
index 06911a7ecd3..54902cb7e72 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/design/frontend/vendor_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme/theme.xml
index 3553148941d..bbde8ed3201 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Custom Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>vendor_default</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme2/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme2/theme.xml
index 27f9932a534..b160a438c65 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme2/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_custom_theme2/theme.xml
@@ -24,6 +24,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Custom Theme 2</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
     <parent>vendor_custom_theme</parent>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_default/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_default/theme.xml
index b42c20a345e..7eaecf3d6d2 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_default/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_default/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_standalone_theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_standalone_theme/theme.xml
index 64b19f7016b..a9171d38fbc 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_standalone_theme/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/fallback/design/frontend/vendor_standalone_theme/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Standalone Theme</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/ExportTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Model/ExportTest.php
index ee9b1da38a1..dba1c994a59 100644
--- a/dev/tests/integration/testsuite/Magento/ImportExport/Model/ExportTest.php
+++ b/dev/tests/integration/testsuite/Magento/ImportExport/Model/ExportTest.php
@@ -67,15 +67,15 @@ class ExportTest extends \PHPUnit_Framework_TestCase
         return array(
             'product' => array(
                 '$entity' => 'catalog_product',
-                '$expectedEntityType' => 'Magento\ImportExport\Model\Export\Entity\Product'
+                '$expectedEntityType' => 'Magento\CatalogImportExport\Model\Export\Product'
             ),
             'customer main data' => array(
                 '$entity' => 'customer',
-                '$expectedEntityType' => 'Magento\Customer\Model\ImportExport\Export\Customer'
+                '$expectedEntityType' => 'Magento\CustomerImportExport\Model\Export\Customer'
             ),
             'customer address' => array(
                 '$entity' => 'customer_address',
-                '$expectedEntityType' => 'Magento\Customer\Model\ImportExport\Export\Address'
+                '$expectedEntityType' => 'Magento\CustomerImportExport\Model\Export\Address'
             )
         );
     }
diff --git a/dev/tests/integration/testsuite/Magento/Install/Model/_files/Magento/Test/etc/module.xml b/dev/tests/integration/testsuite/Magento/Install/Model/_files/Magento/Test/etc/module.xml
index b0d1f35534f..322f774f564 100644
--- a/dev/tests/integration/testsuite/Magento/Install/Model/_files/Magento/Test/etc/module.xml
+++ b/dev/tests/integration/testsuite/Magento/Install/Model/_files/Magento/Test/etc/module.xml
@@ -24,5 +24,5 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Test" version="1.11.0.1" active="true" />
+    <module name="Magento_Test" schema_version="1.11.0.1" active="true" />
 </config>
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Block/Bml/BannersTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Block/Bml/BannersTest.php
new file mode 100644
index 00000000000..339606f3ca8
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Block/Bml/BannersTest.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Paypal\Block\Bml;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+class BannersTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @param int $publisherId
+     * @param int $display
+     * @param int $position
+     * @param int $configPosition
+     * @param bool $isEmptyHtml
+     * @dataProvider testToHtmlDataProvider
+     * @magentoAppIsolation enabled
+     * @magentoAppArea frontend
+     */
+    public function testToHtml($publisherId, $display, $position, $configPosition, $isEmptyHtml)
+    {
+        $paypalConfig = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
+        $paypalConfig->expects($this->any())->method('getBmlPublisherId')->will($this->returnValue($publisherId));
+        $paypalConfig->expects($this->any())->method('getBmlDisplay')->will($this->returnValue($display));
+        $paypalConfig->expects($this->any())->method('getBmlPosition')->will($this->returnValue($configPosition));
+
+        /** @var \Magento\Framework\View\LayoutInterface $layout */
+        $layout = Bootstrap::getObjectManager()->get('Magento\Framework\View\LayoutInterface');
+        $block = $layout->createBlock(
+            'Magento\Paypal\Block\Bml\Banners',
+            '',
+            [
+                'paypalConfig' => $paypalConfig,
+                'data' => ['position' => $position]
+            ]
+        );
+        $block->setTemplate('bml.phtml');
+        $html = $block->toHtml();
+
+        if ($isEmptyHtml) {
+            $this->assertEmpty($html);
+        } else {
+            $this->assertContains('data-pp-pubid="' . $block->getPublisherId() . '"', $html);
+            $this->assertContains('data-pp-placementtype="' . $block->getSize() . '"', $html);
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function testToHtmlDataProvider()
+    {
+        return [
+            [1, 1, 100, 100, false],
+            [0, 1, 100, 100, true],
+            [1, 0, 100, 100, true],
+            [1, 0, 10, 100, true]
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
index 90b5bc8a0cb..c52c685aa57 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php
@@ -28,6 +28,7 @@ use Magento\Customer\Model\Customer;
 use Magento\TestFramework\Helper\Bootstrap;
 use Magento\Checkout\Model\Type\Onepage;
 use Magento\Sales\Model\Quote;
+use Magento\Paypal\Model\Express\Checkout;
 
 class CheckoutTest extends \PHPUnit_Framework_TestCase
 {
@@ -197,6 +198,104 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase
         );
     }
 
+    /**
+     * Verify that an order placed with an existing customer can re-use the customer addresses.
+     *
+     * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
+     * @magentoAppIsolation enabled
+     * @magentoDbIsolation enabled
+     */
+    public function testReturnFromPaypal()
+    {
+        $quote = $this->_getFixtureQuote();
+        $paypalConfigMock = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
+        $apiTypeFactory = $this->getMock('Magento\Paypal\Model\Api\Type\Factory', [], [], '', false);
+        $paypalInfo = $this->getMock('Magento\Paypal\Model\Info', [], [], '', false);
+        $checkoutModel = $this->_objectManager->create(
+            'Magento\Paypal\Model\Express\Checkout',
+            [
+                'params' => ['quote' => $quote, 'config' => $paypalConfigMock],
+                'apiTypeFactory' => $apiTypeFactory,
+                'paypalInfo' => $paypalInfo
+            ]
+        );
+
+        $api = $this->getMock(
+            'Magento\Paypal\Model\Api\Nvp',
+            ['call', 'getExportedShippingAddress', 'getExportedBillingAddress'],
+            [],
+            '',
+            false
+        );
+        $api->expects($this->any())->method('call')->will($this->returnValue(array()));
+        $apiTypeFactory->expects($this->any())->method('create')->will($this->returnValue($api));
+
+        $exportedBillingAddress = $this->_getExportedAddressFixture($quote->getBillingAddress()->getData());
+        $api->expects($this->any())
+            ->method('getExportedBillingAddress')
+            ->will($this->returnValue($exportedBillingAddress));
+
+        $exportedShippingAddress = $this->_getExportedAddressFixture($quote->getShippingAddress()->getData());
+        $api->expects($this->any())
+            ->method('getExportedShippingAddress')
+            ->will($this->returnValue($exportedShippingAddress));
+
+
+        $paypalInfo->expects($this->once())->method('importToPayment')->with($api, $quote->getPayment());
+
+        $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
+
+        $checkoutModel->returnFromPaypal('token');
+
+        $billingAddress = $quote->getBillingAddress();
+        $this->assertEquals($billingAddress->getEmail(), $quote->getCustomerEmail());
+        $this->assertEquals($billingAddress->getPrefix(), $quote->getCustomerPrefix());
+        $this->assertEquals($billingAddress->getFirstname(), $quote->getCustomerFirstname());
+        $this->assertEquals($billingAddress->getMiddlename(), $quote->getCustomerMiddlename());
+        $this->assertEquals($billingAddress->getLastname(), $quote->getCustomerLastname());
+        $this->assertEquals($billingAddress->getSuffix(), $quote->getCustomerSuffix());
+        $this->assertTrue($billingAddress->getShouldIgnoreValidation());
+        $this->assertContains('exported', $billingAddress->getFirstname());
+
+        $shippingAddress = $quote->getShippingAddress();
+        $this->assertTrue((bool)$shippingAddress->getSameAsBilling());
+        $this->assertNull($shippingAddress->getPrefix());
+        $this->assertNull($shippingAddress->getMiddlename());
+        $this->assertNull($shippingAddress->getLastname());
+        $this->assertNull($shippingAddress->getSuffix());
+        $this->assertTrue($shippingAddress->getShouldIgnoreValidation());
+        $this->assertContains('exported', $shippingAddress->getFirstname());
+
+        $paymentAdditionalInformation = $quote->getPayment()->getAdditionalInformation();
+        $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD, $paymentAdditionalInformation);
+        $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_PAYER_ID, $paymentAdditionalInformation);
+        $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_TOKEN, $paymentAdditionalInformation);
+        $this->assertTrue($quote->getPayment()->hasMethod());
+
+        $this->assertTrue($quote->getTotalsCollectedFlag());
+        $this->assertFalse($quote->hasDataChanges());
+    }
+
+    /**
+     * Prepare fixture for exported address
+     *
+     * @param array $addressData
+     * @return \Magento\Framework\Object
+     */
+    protected function _getExportedAddressFixture(array $addressData)
+    {
+        $addressDataKeys = ['firstname', 'lastname', 'street', 'city', 'telephone'];
+        $result = array();
+        foreach ($addressDataKeys as $key) {
+            if (isset($addressData[$key])) {
+                $result[$key] = 'exported' . $addressData[$key];
+            }
+        }
+        $fixture = new \Magento\Framework\Object($result);
+        $fixture->setExportedKeys($addressDataKeys);
+        return $fixture;
+    }
+
     /**
      * @return Quote
      */
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
new file mode 100644
index 00000000000..57529c82584
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
@@ -0,0 +1,205 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation\Rate;
+
+class ConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Tax\Model\Calculation\RateFactory
+     */
+    protected $taxRateFactory;
+
+    public function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->taxRateFactory = $this->objectManager->create('Magento\Tax\Model\Calculation\RateFactory');
+    }
+
+    /**
+     * @param array $data
+     * @dataProvider createTaxRateDataObjectFromModelDataProvider
+     */
+    public function testCreateTaxRateDataObjectFromModel($data)
+    {
+        $taxRateModel = $this->taxRateFactory->create(['data' => $data]);
+
+        $taxRateDataOjectBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $zipRangeDataObjectBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        /** @var  $converter \Magento\Tax\Model\Calculation\Rate\Converter */
+        $converter = $this->objectManager->create(
+            'Magento\Tax\Model\Calculation\Rate\Converter',
+            [
+                'taxRateDataObjectBuilder' => $taxRateDataOjectBuilder,
+                'zipRangeDataObjectBuilder' => $zipRangeDataObjectBuilder,
+            ]
+        );
+        $taxRateDataObject = $converter->createTaxRateDataObjectFromModel($taxRateModel);
+        $this->assertEquals($taxRateModel->getId(), $taxRateDataObject->getId());
+        $this->assertEquals($taxRateModel->getTaxCountryId(), $taxRateDataObject->getCountryId());
+        $this->assertEquals($taxRateModel->getTaxRegionId(), $taxRateDataObject->getRegionId());
+        $this->assertEquals($taxRateModel->getTaxPostcode(), $taxRateDataObject->getPostcode());
+        $this->assertEquals($taxRateModel->getCode(), $taxRateDataObject->getcode());
+        $this->assertEquals($taxRateModel->getRate(), $taxRateDataObject->getPercentageRate());
+        $zipIsRange = $taxRateModel->getZipIsRange();
+        if ($zipIsRange) {
+            $this->assertEquals(
+                $taxRateModel->getZipFrom(),
+                $taxRateDataObject->getZipRange()->getFrom()
+            );
+            $this->assertEquals(
+                $taxRateModel->getZipTo(),
+                $taxRateDataObject->getZipRange()->getTo()
+            );
+        } else {
+            $this->assertNull($taxRateDataObject->getZipRange());
+        }
+    }
+
+    public function createTaxRateDataObjectFromModelDataProvider()
+    {
+        return [
+            [
+                [
+                    'id' => '1',
+                    'countryId' => 'US',
+                    'regionId' => '34',
+                    'code' => 'US-CA-*-Rate 1',
+                    'rate' => '8.25',
+                    'zipIsRange' => '1',
+                    'zipFrom' => '78701',
+                    'zipTo' => '78759',
+                ],
+            ],
+            [
+                [
+                    'id' => '1',
+                    'countryId' => 'US',
+                    'code' => 'US-CA-*-Rate 1',
+                    'rate' => '8.25',
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @param array $data
+     * @dataProvider createTaxRateModelDataProvider
+     */
+    public function testCreateTaxRateModel($data)
+    {
+        $taxRateDataObjectBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $zipRangeDataObjectBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+
+        /** @var  $converter \Magento\Tax\Model\Calculation\Rate\Converter */
+        $converter = $this->objectManager->create(
+            'Magento\Tax\Model\Calculation\Rate\Converter',
+            [
+                'taxRateDataObjectBuilder' => $taxRateDataObjectBuilder,
+                'zipRangeDataObjectBuilder' => $zipRangeDataObjectBuilder,
+            ]
+        );
+
+        $taxRateDataObject = $taxRateDataObjectBuilder->populateWithArray($data)->create();
+        $taxRateModel = $converter->createTaxRateModel($taxRateDataObject);
+
+        //Assertion
+        $this->assertEquals($taxRateDataObject->getId(), $taxRateModel->getId());
+        $this->assertEquals($taxRateDataObject->getCountryId(), $taxRateModel->getTaxCountryId());
+        $this->assertEquals($taxRateDataObject->getRegionId(), $taxRateModel->getTaxRegionId());
+        $this->assertEquals($taxRateDataObject->getPostcode(), $taxRateModel->getTaxPostcode());
+        $this->assertEquals($taxRateDataObject->getcode(), $taxRateModel->getCode());
+        $this->assertEquals($taxRateDataObject->getPercentageRate(), $taxRateModel->getRate());
+        if ($taxRateDataObject->getZipRange()) {
+            if ($taxRateDataObject->getZipRange()->getFrom()) {
+                $this->assertEquals(
+                    $taxRateDataObject->getZipRange()->getFrom(),
+                    $taxRateModel->getZipFrom()
+                );
+            } else {
+                $this->assertNull($taxRateModel->getZipFrom());
+            }
+            if ($taxRateDataObject->getZipRange()->getTo()) {
+                $this->assertEquals(
+                    $taxRateDataObject->getZipRange()->getTo(),
+                    $taxRateModel->getZipTo()
+                );
+            } else {
+                $this->assertNull($taxRateModel->getTo());
+            }
+        } else {
+            $this->assertNull($taxRateModel->getZipFrom());
+            $this->assertNull($taxRateModel->getZipTo());
+        }
+    }
+
+    public function createTaxRateModelDataProvider()
+    {
+        return [
+            'withZipRange' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['from' => 78765, 'to' => 78780]
+                ],
+            ],
+            'withZipRangeFrom' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['from' => 78765]
+                ],
+            ],
+            'withZipRangeTo' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['to' => 78780]
+                ],
+            ],
+            'withPostalCode' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'code' => 'US-CA-*-Rate 1',
+                    'rate' => '8.25',
+                    'postcode' => '78727'
+                ],
+            ]
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/ClassTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/ClassTest.php
index ef0247511ac..dd58d4e0e36 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/Model/ClassTest.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/ClassTest.php
@@ -36,6 +36,9 @@ class ClassTest extends \PHPUnit_Framework_TestCase
         $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
     }
 
+    /**
+     * @magentoDbIsolation enabled
+     */
     public function testCheckClassCanBeDeletedCustomerClassAssertException()
     {
         /** @var $model \Magento\Tax\Model\ClassModel */
@@ -92,6 +95,7 @@ class ClassTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
+     * @magentoDbIsolation enabled
      * @dataProvider classesDataProvider
      */
     public function testCheckClassCanBeDeletedPositiveResult($classType)
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
new file mode 100644
index 00000000000..f8477b69b25
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php
@@ -0,0 +1,289 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Sales\Total\Quote;
+
+use Magento\Framework\Exception\InputException;
+use Magento\Tax\Model\ClassModel;
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * Test \Magento\Tax\Model\Sales\Total\Quote\Subtotal
+ */
+class SubtotalTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+
+    /**
+     * @magentoDataFixture Magento/Customer/_files/customer.php
+     * @magentoDataFixture Magento/Customer/_files/customer_address.php
+     * @magentoDataFixture Magento/Tax/_files/tax_classes.php
+     * @magentoDataFixture Magento/Customer/_files/customer_group.php
+     * @magentoDataFixture Magento/Catalog/_files/products.php
+     * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
+     * @dataProvider collectUnitBasedDataProvider
+     */
+    public function testCollectUnitBased($expected)
+    {
+        $customerTaxClassId = $this->getCustomerTaxClassId();
+        $fixtureCustomerId = 1;
+        /** @var \Magento\Customer\Model\Customer $customer */
+        $customer = $this->objectManager->create('Magento\Customer\Model\Customer')->load($fixtureCustomerId);
+        /** @var \Magento\Customer\Model\Group $customerGroup */
+        $customerGroup = $this->objectManager->create(
+            'Magento\Customer\Model\Group'
+        )->load(
+                'custom_group',
+                'customer_group_code'
+            );
+        $customerGroup->setTaxClassId($customerTaxClassId)->save();
+        $customer->setGroupId($customerGroup->getId())->save();
+
+        $productTaxClassId = $this->getProductTaxClassId();
+        $fixtureProductId = 1;
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product')->load($fixtureProductId);
+        $product->setTaxClassId($productTaxClassId)->save();
+
+        $quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId);
+
+        /** @var \Magento\Sales\Model\Quote\Address $quoteShippingAddress */
+        $quoteShippingAddress = $this->objectManager->create('Magento\Sales\Model\Quote\Address');
+        $quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject);
+        $quantity = 2;
+
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->setStoreId(
+                1
+            )->setIsActive(
+                true
+            )->setIsMultiShipping(
+                false
+            )->assignCustomerWithAddressChange(
+                $customer
+            )->setShippingAddress(
+                $quoteShippingAddress
+            )->setBillingAddress(
+                $quoteShippingAddress
+            )->setCheckoutMethod(
+                $customer->getMode()
+            )->setPasswordHash(
+                $customer->encryptPassword($customer->getPassword())
+            )->addProduct(
+                $product->load($product->getId()),
+                $quantity
+            );
+        $address = $quote->getShippingAddress();
+
+        /** @var \Magento\Sales\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
+        $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->collect($address);
+
+        $this->assertEquals($expected['subtotal'], $address->getSubtotal());
+        $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getSubtotalInclTax());
+        $this->assertEquals($expected['discount_amount'], $address->getDiscountAmount());
+        $items = $address->getAllItems();
+        /** @var \Magento\Sales\Model\Quote\Address\Item $item */
+        $item = $items[0];
+        $this->assertEquals($expected['items'][0]['price'], $item->getPrice());
+        $this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax());
+        $this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal());
+        $this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax());
+        $this->assertEquals($expected['items'][0]['taxable_amount'], $item->getTaxableAmount());
+        $this->assertEquals($expected['items'][0]['tax_percent'], $item->getTaxPercent());
+    }
+
+    public function collectUnitBasedDataProvider()
+    {
+        return [
+            'one_item' => [
+                [
+                    'subtotal' => 20,
+                    'tax_amount' => 1.5,
+                    'discount_amount' => 0,
+                    'items' => [
+                        [
+                            'tax_amount' => 1.5,
+                            'price' => 10,
+                            'price_incl_tax' => 10.75,
+                            'row_total' => 20,
+                            'row_total_incl_tax' => 21.5,
+                            'taxable_amount' => 10,
+                            'code' => 'simple',
+                            'type' => 'product',
+                            'tax_percent' => 7.5,
+                        ],
+                    ],
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @magentoDataFixture Magento/Customer/_files/customer.php
+     * @magentoDataFixture Magento/Customer/_files/customer_address.php
+     * @magentoDataFixture Magento/Tax/_files/tax_classes.php
+     * @magentoDataFixture Magento/Customer/_files/customer_group.php
+     * @magentoDataFixture Magento/Bundle/_files/product.php
+     * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
+     * @dataProvider collectUnitBasedDataProvider
+     */
+    public function testCollectUnitBasedBundleProduct($expected)
+    {
+        $customerTaxClassId = $this->getCustomerTaxClassId();
+        $fixtureCustomerId = 1;
+        /** @var \Magento\Customer\Model\Customer $customer */
+        $customer = $this->objectManager->create('Magento\Customer\Model\Customer')->load($fixtureCustomerId);
+        /** @var \Magento\Customer\Model\Group $customerGroup */
+        $customerGroup = $this->objectManager->create(
+            'Magento\Customer\Model\Group'
+        )->load(
+                'custom_group',
+                'customer_group_code'
+            );
+        $customerGroup->setTaxClassId($customerTaxClassId)->save();
+        $customer->setGroupId($customerGroup->getId())->save();
+
+        $productTaxClassId = $this->getProductTaxClassId();
+        $fixtureChildProductId = 1;
+        /** @var \Magento\Catalog\Model\Product $product */
+        $childProduct = $this->objectManager->create('Magento\Catalog\Model\Product')->load($fixtureChildProductId);
+        $childProduct->setTaxClassId($productTaxClassId)->save();
+        $fixtureProductId = 3;
+        /** @var \Magento\Catalog\Model\Product $product */
+        $product = $this->objectManager->create('Magento\Catalog\Model\Product')->load($fixtureProductId);
+        $product->setTaxClassId($productTaxClassId)
+            ->setPriceType(\Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD)
+            ->save();
+
+        $quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId);
+
+        /** @var \Magento\Sales\Model\Quote\Address $quoteShippingAddress */
+        $quoteShippingAddress = $this->objectManager->create('Magento\Sales\Model\Quote\Address');
+        $quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject);
+        $quantity = 2;
+
+        /** @var \Magento\Sales\Model\Quote $quote */
+        $quote = $this->objectManager->create('Magento\Sales\Model\Quote');
+        $quote->setStoreId(
+                1
+            )->setIsActive(
+                true
+            )->setIsMultiShipping(
+                false
+            )->assignCustomerWithAddressChange(
+                $customer
+            )->setShippingAddress(
+                $quoteShippingAddress
+            )->setBillingAddress(
+                $quoteShippingAddress
+            )->setCheckoutMethod(
+                $customer->getMode()
+            )->setPasswordHash(
+                $customer->encryptPassword($customer->getPassword())
+            )->addProduct(
+                $product->load($product->getId()),
+                $quantity
+            );
+        $address = $quote->getShippingAddress();
+
+        /** @var \Magento\Sales\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
+        $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->collect($address);
+
+        $this->assertEquals($expected['subtotal'], $address->getSubtotal());
+        $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getSubtotalInclTax());
+        $this->assertEquals($expected['discount_amount'], $address->getDiscountAmount());
+        $items = $address->getAllItems();
+        /** @var \Magento\Sales\Model\Quote\Address\Item $item */
+        $item = $items[0];
+        $this->assertEquals($expected['items'][0]['price'], $item->getPrice());
+        $this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax());
+        $this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal());
+        $this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax());
+    }
+
+    /**
+     * Get customer tax class id
+     *
+     * @return int
+     */
+    protected function getCustomerTaxClassId()
+    {
+        $customerTaxClass = $this->objectManager->create('Magento\Tax\Model\ClassModel');
+        $fixtureCustomerTaxClass = 'CustomerTaxClass2';
+        /** @var \Magento\Tax\Model\ClassModel $customerTaxClass */
+        $customerTaxClass->load($fixtureCustomerTaxClass, 'class_name');
+        return $customerTaxClass->getId();
+    }
+
+    /**
+     * Get product tax class id
+     *
+     * @return int
+     */
+    protected function getProductTaxClassId()
+    {
+        /** @var \Magento\Tax\Model\ClassModel $productTaxClass */
+        $productTaxClass = $this->objectManager->create('Magento\Tax\Model\ClassModel');
+        $fixtureProductTaxClass = 'ProductTaxClass1';
+        $productTaxClass->load($fixtureProductTaxClass, 'class_name');
+        return $productTaxClass->getId();
+    }
+
+    /**
+     * @param $fixtureCustomerId
+     * @return \Magento\Customer\Service\V1\Data\Address
+     */
+    protected function getShippingAddressDataObject($fixtureCustomerId)
+    {
+        $fixtureCustomerAddressId = 1;
+        $customerAddress = $this->objectManager->create('Magento\Customer\Model\Address')->load($fixtureCustomerId);
+        /** Set data which corresponds tax class fixture */
+        $customerAddress->setCountryId('US')->setRegionId(12)->save();
+        /** @var \Magento\Customer\Service\V1\CustomerAddressServiceInterface $addressService */
+        $addressService = $this->objectManager->create('Magento\Customer\Service\V1\CustomerAddressServiceInterface');
+        $quoteShippingAddressDataObject = $addressService->getAddress($fixtureCustomerAddressId);
+        return $quoteShippingAddressDataObject;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
new file mode 100644
index 00000000000..84556366d4b
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/QuoteDetailsBuilderTest.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+
+class QuoteDetailsBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\ObjectManager */
+    private $objectManager;
+
+    /** @var QuoteDetailsBuilder */
+    private $builder;
+
+    /* @var QuoteDetails\ItemBuilder */
+    private $itemBuilder;
+
+    /* @var \Magento\Customer\Service\V1\Data\AddressBuilder */
+    private $addressBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Tax\Service\V1\Data\QuoteDetailsBuilder');
+        $this->itemBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder');
+        $this->addressBuilder = $this->objectManager->create('\Magento\Customer\Service\V1\Data\AddressBuilder');
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $items
+     * @dataProvider createDataProvider
+     */
+    public function testCreateWithPopulateWithArray($dataArray, $items = [])
+    {
+        if (!empty($items)) {
+            $dataArray[QuoteDetails::KEY_ITEMS] = $items;
+        }
+        $taxRate = $this->builder->populateWithArray($dataArray)->create();
+
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\QuoteDetails', $taxRate);
+        $this->assertEquals($dataArray, $taxRate->__toArray());
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $items
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray, $items = [])
+    {
+        if (!empty($items)) {
+            $dataArray[QuoteDetails::KEY_ITEMS] = $items;
+        }
+        $taxRate = $this->builder->populateWithArray($dataArray)->create();
+        $taxRate2 = $this->builder->populate($taxRate)->create();
+
+        $this->assertEquals($taxRate, $taxRate2);
+    }
+
+    public function createDataProvider()
+    {
+        $data = $this->getData()['dataMerged'];
+        $items = $data[QuoteDetails::KEY_ITEMS];
+        unset($data[QuoteDetails::KEY_ITEMS]);
+
+        return [
+            'withEmptyData' => [[],[]],
+            'withEmptyQuoteItems' => [$data],
+            'withQuoteItems' => [[], $items],
+            'withQuoteDetailsAndItems' => [$data, $items]
+        ];
+    }
+
+    public function testMergeDataObjects()
+    {
+        $data = $this->getData();
+        $taxRate = $this->builder->populateWithArray($data['dataMerged'])->create();
+        $taxRate1 = $this->builder->populateWithArray($data['data1'])->create();
+        $taxRate2 = $this->builder->populateWithArray($data['data2'])->create();
+        $taxRateMerged = $this->builder->mergeDataObjects($taxRate1, $taxRate2);
+        $this->assertEquals($taxRate->__toArray(), $taxRateMerged->__toArray());
+    }
+
+    public function testMergeDataObjectWithArray()
+    {
+        $data = $this->getData();
+
+        $taxRate = $this->builder->populateWithArray($data['dataMerged'])->create();
+        $taxRate1 = $this->builder->populateWithArray($data['data1'])->create();
+        $taxRateMerged = $this->builder->mergeDataObjectWithArray($taxRate1, $data['data2']);
+        $this->assertEquals($taxRate->__toArray(), $taxRateMerged->__toArray());
+    }
+
+    /**
+     * @return array
+     */
+    protected function getData()
+    {
+        $addressData = [
+            'id' => 14,
+            'default_shipping' => true,
+            'default_billing' => true,
+            'company' => 'Company Name',
+            'fax' => '(555) 555-5555',
+            'middlename' => 'Mid',
+            'prefix' => 'Mr.',
+            'suffix' => 'Esq.',
+            'vat_id' => 'S45',
+            'firstname' => 'Jane',
+            'lastname' => 'Doe',
+            'street' => ['7700 W Parmer Ln'],
+            'city' => 'Austin',
+            'country_id' => 'US',
+            'postcode' => '78620',
+            'telephone' => '5125125125',
+            'region' => ['region_id' => 0, 'region' => 'Texas']
+        ];
+
+        $items = [
+            [
+                'code' => 'item code',
+                'type' => 'shipping',
+                'discount_amount' => 2.6
+            ],
+            [
+                'code' => 'another code',
+                'type' => 'product',
+                'discount_amount' => 5
+            ]
+        ];
+        $data = [
+            'data1' => [
+                QuoteDetails::KEY_BILLING_ADDRESS => $addressData,
+                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID => 1,
+            ],
+            'data2' => [
+                QuoteDetails::KEY_SHIPPING_ADDRESS => $addressData,
+                QuoteDetails::KEY_ITEMS => $items
+            ],
+            'dataMerged' => [
+                QuoteDetails::KEY_BILLING_ADDRESS => $addressData,
+                QuoteDetails::KEY_SHIPPING_ADDRESS => $addressData,
+                QuoteDetails::KEY_CUSTOMER_TAX_CLASS_ID => 1,
+                QuoteDetails::KEY_ITEMS => $items
+            ]
+        ];
+
+        return $data;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilderTest.php
new file mode 100644
index 00000000000..1c5c3aa521d
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/AppliedTaxBuilderTest.php
@@ -0,0 +1,244 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+/**
+ * Integration test for \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder
+ */
+class AppliedTaxBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * AppliedTax builder
+     *
+     * @var AppliedTaxBuilder
+     */
+    private $builder;
+
+    /**
+     * AppliedTaxRate builder
+     *
+     * @var AppliedTaxRateBuilder
+     */
+    private $appliedTaxRateBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder');
+        $this->appliedTaxRateBuilder = $this->objectManager->create(
+            'Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxRateBuilder'
+        );
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $appliedTaxRatesArray
+     * @dataProvider createDataProvider
+     */
+    public function testCreateWithPopulateWithArray($dataArray, $appliedTaxRatesArray = [])
+    {
+        if (!empty($appliedTaxRatesArray)) {
+            $dataArray[AppliedTax::KEY_RATES] = $appliedTaxRatesArray;
+        }
+        $appliedTax = $this->builder->populateWithArray($dataArray)->create();
+        $appliedTax2 = $this->generateDataObjectWithSetters($dataArray);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax', $appliedTax);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax', $appliedTax2);
+        $this->assertEquals($appliedTax2, $appliedTax);
+        $this->assertEquals($dataArray, $appliedTax->__toArray());
+        $this->assertEquals($dataArray, $appliedTax2->__toArray());
+    }
+
+    public function createDataProvider()
+    {
+        $data = [
+            'tax_rate_key' => 'key',
+            'percent' => '8.25',
+            'amount' => '8',
+        ];
+
+        $ratesData = [
+            [
+                'code' => 'rate1',
+                'title' => 'rate1Title',
+                'percent' => '8.25',
+            ],
+            [
+                'code' => 'rate2',
+                'title' => 'rate2Title',
+                'percent' => '7.25',
+            ],
+        ];
+        return [
+            'no_data' => [[]],
+            'no_rates' => [$data],
+            'data_n_rates' => [$data, $ratesData],
+            'rates_only' => [[], $ratesData],
+        ];
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $appliedTaxRatesArray
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray, $appliedTaxRatesArray = [])
+    {
+        if (!empty($appliedTaxRatesArray)) {
+            $dataArray[AppliedTax::KEY_RATES] = $appliedTaxRatesArray;
+        }
+        $appliedTax = $this->generateDataObjectWithSetters($dataArray);
+        $appliedTax2 = $this->builder->populate($appliedTax)->create();
+        $this->assertEquals($appliedTax, $appliedTax2);
+    }
+
+    public function testMergeDataObjects()
+    {
+        $data1 = [
+            'tax_rate_key' => 'key',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate1',
+                    'title' => 'rate1Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $data2 = [
+            'tax_rate_key' => 'key2',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate2',
+                    'title' => 'rate2Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $dataMerged = [
+            'tax_rate_key' => 'key2',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate2',
+                    'title' => 'rate2Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $appliedTax = $this->builder->populateWithArray($dataMerged)->create();
+        $appliedTax1 = $this->builder->populateWithArray($data1)->create();
+        $appliedTax2 = $this->builder->populateWithArray($data2)->create();
+        $appliedTaxMerged = $this->builder->mergeDataObjects($appliedTax1, $appliedTax2);
+        $this->assertEquals($appliedTax->__toArray(), $appliedTaxMerged->__toArray());
+    }
+
+    public function testMergeDataObjectWithArray()
+    {
+        $data1 = [
+            'tax_rate_key' => 'key',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate1',
+                    'title' => 'rate1Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $data2 = [
+            'tax_rate_key' => 'key2',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate2',
+                    'title' => 'rate2Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $dataMerged = [
+            'tax_rate_key' => 'key2',
+            'percent' => '8.25',
+            'amount' => '8',
+            'rates' => [
+                [
+                    'code' => 'rate2',
+                    'title' => 'rate2Title',
+                    'percent' => '8.25',
+                ],
+            ],
+        ];
+
+        $appliedTax = $this->builder->populateWithArray($dataMerged)->create();
+        $appliedTax1 = $this->builder->populateWithArray($data1)->create();
+        $appliedTaxMerged = $this->builder->mergeDataObjectWithArray($appliedTax1, $data2);
+        $this->assertEquals($appliedTax->__toArray(), $appliedTaxMerged->__toArray());
+    }
+
+    /**
+     * @param array $dataArray
+     * @return AppliedTax
+     */
+    protected function generateDataObjectWithSetters($dataArray)
+    {
+        $this->builder->populateWithArray([]);
+        if (array_key_exists(AppliedTax::KEY_TAX_RATE_KEY, $dataArray)) {
+            $this->builder->setTaxRateKey($dataArray[AppliedTax::KEY_TAX_RATE_KEY]);
+        }
+        if (array_key_exists(AppliedTax::KEY_PERCENT, $dataArray)) {
+            $this->builder->setPercent($dataArray[AppliedTax::KEY_PERCENT]);
+        }
+        if (array_key_exists(AppliedTax::KEY_AMOUNT, $dataArray)) {
+            $this->builder->setAmount($dataArray[AppliedTax::KEY_AMOUNT]);
+        }
+        if (array_key_exists(AppliedTax::KEY_RATES, $dataArray)) {
+            $rates = [];
+            foreach ($dataArray[AppliedTax::KEY_RATES] as $rateArray) {
+                $rates[] = $this->appliedTaxRateBuilder->populateWithArray($rateArray)
+                    ->create();
+            }
+            $this->builder->setRates($rates);
+        }
+        return $this->builder->create();
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilderTest.php
new file mode 100644
index 00000000000..eea950fd930
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetails/ItemBuilderTest.php
@@ -0,0 +1,231 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data\TaxDetails;
+
+class ItemBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Applied Tax data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder
+     */
+    private $appliedTaxBuilder;
+
+    /**
+     * Tax Details Item data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder
+     */
+    private $taxDetailsItemBuilder;
+
+    private static $travisCtyRateObjectDataArray = [
+        'code' => '9',
+        'title' => 'TX-TRAVIS',
+        'percent' => 0.0825,
+    ];
+
+    private static $utopiaCtyRateObjectDataArray = [
+        'code' => '2',
+        'title' => 'TX-UTOPIA',
+        'percent' => 0.01,
+    ];
+
+    private static $noTaxRateObjectDataArray = [
+        'code' => '5',
+        'title' => 'TX-FREE',
+        'percent' => 0.00,
+    ];
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->appliedTaxBuilder = $this->objectManager
+            ->create('\Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder');
+        $this->taxDetailsItemBuilder = $this->objectManager
+            ->create('\Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder');
+    }
+
+    public function testTaxDetailsNoItemTax()
+    {
+        $appliedTaxDataArray = [
+            'tax_rate_key' => '0',
+            'percent' => 0.00,
+            'amount' => 0.00,
+            'rates' => [
+                $this::$noTaxRateObjectDataArray,
+            ],
+        ];
+
+        $taxDetailsItemDataArray = [
+            'code' => 'FOO123',
+            'type' => 'product',
+            'tax_percent' => 0.00,
+            'price' => 9.99,
+            'price_incl_tax' => 9.99,
+            'row_total' => 9.99,
+            'row_tax' => 0.00,
+            'taxable_amount' => 9.99,
+            'discount_amount' => 0.00,
+            'discount_tax_compensation_amount' => 0.00,
+            'applied_taxes' => [
+                $appliedTaxDataArray
+            ],
+        ];
+
+        $taxDetailsItemObjectFromArray = $this->taxDetailsItemBuilder
+            ->populateWithArray($taxDetailsItemDataArray)
+            ->create();
+
+        $taxDetailsItemObjectFromObject = $this->taxDetailsItemBuilder
+            ->populate($taxDetailsItemObjectFromArray)
+            ->create();
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromArray->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromObject->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemObjectFromArray,
+            $taxDetailsItemObjectFromObject
+        );
+    }
+
+    public function testTaxDetailsItemSingleTax()
+    {
+        $appliedTaxDataArray = [
+            'tax_rate_key' => '1',
+            'percent' => 0.0825,
+            'amount' => 0.82,
+            'rates' => [
+                self::$travisCtyRateObjectDataArray,
+            ],
+        ];
+
+        $taxDetailsItemDataArray = [
+            'code' => 'ABC123',
+            'type' => 'product',
+            'tax_percent' => 0.0825,
+            'price' => 9.99,
+            'price_incl_tax' => 10.81,
+            'row_total' => 9.99,
+            'row_tax' => 0.82,
+            'taxable_amount' => 9.99,
+            'discount_amount' => 0.00,
+            'discount_tax_compensation_amount' => 0.00,
+            'applied_taxes' => [
+                $appliedTaxDataArray
+            ],
+        ];
+
+        $taxDetailsItemObjectFromArray = $this->taxDetailsItemBuilder
+            ->populateWithArray($taxDetailsItemDataArray)
+            ->create();
+
+        $taxDetailsItemObjectFromObject = $this->taxDetailsItemBuilder
+            ->populate($taxDetailsItemObjectFromArray)
+            ->create();
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromArray->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromObject->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemObjectFromArray,
+            $taxDetailsItemObjectFromObject
+        );
+    }
+
+    public function testTaxDetailsItemMultipleTaxes()
+    {
+        $appliedTaxDataArray = [
+            'tax_rate_key' => '77',
+            'percent' => 0.0925,
+            'amount' => 0.82,
+            'rates' => [
+                self::$travisCtyRateObjectDataArray,
+                self::$utopiaCtyRateObjectDataArray,
+                self::$noTaxRateObjectDataArray,
+            ],
+        ];
+
+        $taxDetailsItemDataArray = [
+            'code' => 'QWERTY123',
+            'type' => 'product',
+            'tax_percent' => 0.0925,
+            'price' => 4.99,
+            'price_incl_tax' => 5.45,
+            'row_total' => 4.99,
+            'row_tax' => 0.64,
+            'taxable_amount' => 4.99,
+            'discount_amount' => 0.00,
+            'discount_tax_compensation_amount' => 0.00,
+            'applied_taxes' => [
+                $appliedTaxDataArray
+            ],
+        ];
+
+        $taxDetailsItemObjectFromArray = $this->taxDetailsItemBuilder
+            ->populateWithArray($taxDetailsItemDataArray)
+            ->create();
+
+        $taxDetailsItemObjectFromObject = $this->taxDetailsItemBuilder
+            ->populate($taxDetailsItemObjectFromArray)
+            ->create();
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromArray->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemDataArray,
+            $taxDetailsItemObjectFromObject->__toArray()
+        );
+
+        $this->assertEquals(
+            $taxDetailsItemObjectFromArray,
+            $taxDetailsItemObjectFromObject
+        );
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetailsBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetailsBuilderTest.php
new file mode 100644
index 00000000000..0d1d0f7b4ca
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxDetailsBuilderTest.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1\Data;
+
+class TaxDetailsBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Applied Tax data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder
+     */
+    private $appliedTaxBuilder;
+
+    /**
+     * Tax Details Item data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder
+     */
+    private $taxDetailsItemBuilder;
+
+    /**
+     * Tax Details data object builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxDetailsBuilder
+     */
+    private $taxDetailsBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->appliedTaxBuilder = $this->objectManager
+            ->create('\Magento\Tax\Service\V1\Data\TaxDetails\AppliedTaxBuilder');
+        $this->taxDetailsItemBuilder = $this->objectManager
+            ->create('\Magento\Tax\Service\V1\Data\TaxDetails\ItemBuilder');
+        $this->taxDetailsBuilder = $this->objectManager
+            ->create('\Magento\Tax\Service\V1\Data\TaxDetailsBuilder');
+    }
+
+    /**
+     * @param array $taxDetailsDataArray
+     *
+     * @dataProvider taxDetailsPopulateDataProvider
+     */
+    public function testTaxDetailsPopulate($taxDetailsDataArray)
+    {
+        $taxDetailsDataObjectFromArray = $this->taxDetailsBuilder
+            ->populateWithArray($taxDetailsDataArray)
+            ->create();
+        $taxDetailsDataObjectFromObject = $this->taxDetailsBuilder
+            ->populate($taxDetailsDataObjectFromArray)
+            ->create();
+
+        $this->assertEquals(
+            $taxDetailsDataArray,
+            $taxDetailsDataObjectFromArray->__toArray()
+        );
+        $this->assertEquals(
+            $taxDetailsDataArray,
+            $taxDetailsDataObjectFromObject->__toArray()
+        );
+        $this->assertEquals(
+            $taxDetailsDataObjectFromArray,
+            $taxDetailsDataObjectFromObject
+        );
+    }
+
+    public function taxDetailsPopulateDataProvider()
+    {
+        $appliedTaxDataArray = [
+            'tax_rate_key' => '1',
+            'percent' => 0.0825,
+            'amount' => 1.65,
+            'rates' => [
+                [
+                    'code' => '9',
+                    'title' => 'TX-TRAVIS',
+                    'percent' => 0.0825,
+                ]
+            ],
+        ];
+
+        $taxDetailsItemDataArray = [
+            'code' => '123123',
+            'type' => 'product',
+            'tax_percent' => 0.0825,
+            'price' => 19.99,
+            'price_incl_tax' => 21.64,
+            'row_total' => 19.99,
+            'row_tax' => 1.65,
+            'taxable_amount' => 19.99,
+            'discount_amount' => 0.00,
+            'discount_tax_compensation_amount' => 0.00,
+            'applied_taxes' => [
+                $appliedTaxDataArray,
+            ],
+        ];
+
+        return [
+            'no_items' => [[
+                'subtotal' => 9.99,
+                'tax_amount' => 0.00,
+                'discount_amount' => 0.00,
+            ]],
+            'single_item' => [[
+                'subtotal' => 19.99,
+                'tax_amount' => 1.65,
+                'discount_amount' => 0.00,
+                'applied_taxes' => [
+                    $appliedTaxDataArray,
+                ],
+                'items' => [
+                    $taxDetailsItemDataArray,
+                ],
+            ]],
+            'multiple_items' => [[
+                'subtotal' => 19.99,
+                'tax_amount' => 1.65,
+                'discount_amount' => 0.00,
+                'applied_taxes' => [
+                    $appliedTaxDataArray,
+                    $appliedTaxDataArray,
+                    $appliedTaxDataArray,
+                ],
+                'items' => [
+                    $taxDetailsItemDataArray,
+                    $taxDetailsItemDataArray,
+                    $taxDetailsItemDataArray,
+                ],
+            ]],
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRateBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRateBuilderTest.php
new file mode 100644
index 00000000000..0a94d37f9e7
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRateBuilderTest.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+/**
+ * Integration test for \Magento\Tax\Service\V1\Data\TaxRateBuilder
+ */
+class TaxRateBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxRate builder
+     *
+     * @var TaxRateBuilder
+     */
+    private $builder;
+
+    /**
+     * ZipRange builder
+     *
+     * @var ZipRangeBuilder
+     */
+    private $zipRangeBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $this->zipRangeBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $zipRangeArray
+     * @dataProvider createDataProvider
+     */
+    public function testCreateWithPopulateWithArray($dataArray, $zipRangeArray = [])
+    {
+        if (!empty($zipRangeArray)) {
+            $dataArray[TaxRate::KEY_ZIP_RANGE] = $zipRangeArray;
+        }
+        $taxRate = $this->builder->populateWithArray($dataArray)->create();
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRate', $taxRate);
+        $this->assertEquals($dataArray, $taxRate->__toArray());
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $zipRangeArray
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray, $zipRangeArray = [])
+    {
+        if (!empty($zipRangeArray)) {
+            $dataArray[TaxRate::KEY_ZIP_RANGE] = $zipRangeArray;
+        }
+        $taxRateFromArray = $this->builder->populateWithArray($dataArray)->create();
+        $taxRate = $this->builder->populate($taxRateFromArray)->create();
+        $this->assertEquals($taxRateFromArray, $taxRate);
+    }
+
+    public function createDataProvider()
+    {
+
+        $data = [
+            'id' => 1,
+            'country_id' => 'US',
+            'region_id' => '8',
+            'postcode' => '78729',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate 1',
+        ];
+
+        return [
+            'just data'             => [$data],
+            'just empty data'       => [[]],
+            'data and ziprange'     => [$data, ['from' => 78701, 'to' => 78780]],
+            'data and just from'    => [$data, ['from' => 78701]],
+            'no data and ziprange'  => [[], ['from' => 78701, 'to' => 78780]],
+            'no data and just from' => [[], ['from' => 78701]],
+        ];
+    }
+
+    /**
+     * @dataProvider mergeDataProvider
+     */
+    public function testMergeDataObjects($firstRateArray, $secondRateArray, $expectedResultsArray)
+    {
+        $expectedTaxRate = $this->builder->populateWithArray($expectedResultsArray)->create();
+        $taxRate1 = $this->builder->populateWithArray($firstRateArray)->create();
+        $taxRate2 = $this->builder->populateWithArray($secondRateArray)->create();
+        $taxRateMerged = $this->builder->mergeDataObjects($taxRate1, $taxRate2);
+        $this->assertEquals($expectedTaxRate->__toArray(), $taxRateMerged->__toArray());
+    }
+
+    /**
+     * @dataProvider mergeDataProvider
+     */
+    public function testMergeDataObjectWithArray($firstRateArray, $secondRateArray, $expectedResultsArray)
+    {
+
+        $taxRate = $this->builder->populateWithArray($expectedResultsArray)->create();
+        $taxRate1 = $this->builder->populateWithArray($firstRateArray)->create();
+        $taxRateMerged = $this->builder->mergeDataObjectWithArray($taxRate1, $secondRateArray);
+        $this->assertEquals($taxRate->__toArray(), $taxRateMerged->__toArray());
+    }
+
+    public function mergeDataProvider()
+    {
+        return [
+            'basicMerge' => [
+                'postcode' => [
+                    'id' => 1,
+                    'country_id' => 'US',
+                    'region_id' => 7,
+                    'postcode' => '78729',
+                    'percentage_rate' => 8.25,
+                    'code' => 'US-CA-*-Rate 1',
+                ],
+                'ziprange' => [
+                    'id' => 1,
+                    'country_id' => 'US',
+                    'percentage_rate' => 8.00,
+                    'code' => 'US-CA-*-Rate 1',
+                    'zip_range' => ['from' => 78701, 'to' => 78780]
+                ],
+                'merged' => [
+                    'id' => 1,
+                    'country_id' => 'US',
+                    'region_id' => 7,
+                    'postcode' => '78729',
+                    'percentage_rate' => 8.0,
+                    'code' => 'US-CA-*-Rate 1',
+                    'zip_range' => ['from' => 78701, 'to' => 78780]
+                ],
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleBuilderTest.php
new file mode 100644
index 00000000000..5855de2e250
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleBuilderTest.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+/**
+ * Integration test for \Magento\Tax\Service\V1\Data\TaxRuleBuilder
+ */
+class TaxRuleBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxRule builder
+     *
+     * @var TaxRuleBuilder
+     */
+    private $builder;
+
+    /**
+     * TaxRate builder
+     *
+     * @var TaxRateBuilder
+     */
+    private $taxRateBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $this->taxRateBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+    }
+
+    /**
+     * @param array $dataArray Array with data for TaxRule
+     * @dataProvider createDataProvider
+     */
+    public function testPopulateWithArray($dataArray)
+    {
+        $taxRuleFromPopulate = $this->builder->populateWithArray($dataArray)->create();
+        $taxRuleFromSetters = $this->generateTaxRuleWithSetters($dataArray);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRule', $taxRuleFromPopulate);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRule', $taxRuleFromSetters);
+        $this->assertEquals($taxRuleFromSetters, $taxRuleFromPopulate);
+        $this->assertEquals($dataArray, $taxRuleFromPopulate->__toArray());
+        $this->assertEquals($dataArray, $taxRuleFromSetters->__toArray());
+    }
+
+    /**
+     * @param array $dataArray Array with data for TaxRule
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray)
+    {
+        $taxRuleFromSetters = $this->generateTaxRuleWithSetters($dataArray);
+        $taxRuleFromPopulate = $this->builder->populate($taxRuleFromSetters)->create();
+        $this->assertEquals($taxRuleFromSetters, $taxRuleFromPopulate);
+    }
+
+    public function createDataProvider()
+    {
+        return[
+            'empty' => [[]],
+            'all' => [
+                [
+                    TaxRule::ID => 1,
+                    TaxRule::CODE => 'code',
+                    TaxRule::CUSTOMER_TAX_CLASS_IDS => [1, 2],
+                    TaxRule::PRODUCT_TAX_CLASS_IDS => [3, 4],
+                    TaxRule::TAX_RATE_IDS => [1, 3],
+                    TaxRule::PRIORITY => 0,
+                    TaxRule::SORT_ORDER => 1,
+                ]
+            ],
+            'one rate' => [
+                [
+                    TaxRule::ID => 1,
+                    TaxRule::TAX_RATE_IDS => [1]
+                ]
+            ],
+            'multiple rates' => [
+                [
+                    TaxRule::ID => 1,
+                    TaxRule::CODE => 'code',
+                    TaxRule::CUSTOMER_TAX_CLASS_IDS => [1],
+                    TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+                    TaxRule::TAX_RATE_IDS => [1,2,3,4],
+                    TaxRule::PRIORITY => 0,
+                    TaxRule::SORT_ORDER => 1,
+                ]
+            ],
+        ];
+    }
+
+    public function testMergeDataObjects()
+    {
+        $taxRuleDataSomeFields = [
+                TaxRule::ID => 1,
+                TaxRule::CODE => 'code',
+                TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        $taxRuleDataMoreFields = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'codeChanged',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $taxRuleDataExpected = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'codeChanged',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+            TaxRule::TAX_RATE_IDS => [1],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $taxRuleExpected = $this->builder->populateWithArray($taxRuleDataExpected)->create();
+        $taxRuleSomeFields = $this->builder->populateWithArray($taxRuleDataSomeFields)->create();
+        $taxRuleMoreFields = $this->builder->populateWithArray($taxRuleDataMoreFields)->create();
+        $taxRuleMerged = $this->builder->mergeDataObjects($taxRuleSomeFields, $taxRuleMoreFields);
+        $this->assertEquals($taxRuleExpected->__toArray(), $taxRuleMerged->__toArray());
+    }
+
+    public function testMergeDataObjectsWithArray()
+    {
+        $taxRuleDataSomeFields = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'code',
+            TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        $taxRuleDataMoreFields = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'codeChanged',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $taxRuleDataExpected = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'codeChanged',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+            TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        $taxRuleExpected = $this->builder->populateWithArray($taxRuleDataExpected)->create();
+        $taxRuleSomeFields = $this->builder->populateWithArray($taxRuleDataSomeFields)->create();
+        $taxRuleMerged = $this->builder->mergeDataObjectWithArray($taxRuleSomeFields, $taxRuleDataMoreFields);
+        $this->assertEquals($taxRuleExpected->__toArray(), $taxRuleMerged->__toArray());
+    }
+
+    /**
+     * Creates a TaxRule data object by calling setters for known keys of TaxRule that are in dataArray.
+     *
+     * @param array $dataArray
+     * @return TaxRule
+     */
+    private function generateTaxRuleWithSetters($dataArray)
+    {
+        $this->builder->populateWithArray([]);
+        if (array_key_exists(TaxRule::ID, $dataArray)) {
+            $this->builder->setId($dataArray[TaxRule::ID]);
+        }
+        if (array_key_exists(TaxRule::CODE, $dataArray)) {
+            $this->builder->setCode($dataArray[TaxRule::CODE]);
+        }
+        if (array_key_exists(TaxRule::CUSTOMER_TAX_CLASS_IDS, $dataArray)) {
+            $this->builder->setCustomerTaxClassIds($dataArray[TaxRule::CUSTOMER_TAX_CLASS_IDS]);
+        }
+        if (array_key_exists(TaxRule::PRODUCT_TAX_CLASS_IDS, $dataArray)) {
+            $this->builder->setProductTaxClassIds($dataArray[TaxRule::PRODUCT_TAX_CLASS_IDS]);
+        }
+        if (array_key_exists(TaxRule::TAX_RATE_IDS, $dataArray)) {
+            $this->builder->setTaxRateIds($dataArray[TaxRule::TAX_RATE_IDS]);
+        }
+        if (array_key_exists(TaxRule::PRIORITY, $dataArray)) {
+            $this->builder->setPriority($dataArray[TaxRule::PRIORITY]);
+        }
+        if (array_key_exists(TaxRule::SORT_ORDER, $dataArray)) {
+            $this->builder->setSortOrder($dataArray[TaxRule::SORT_ORDER]);
+        }
+        return $this->builder->create();
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilderTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilderTest.php
new file mode 100644
index 00000000000..5d21048ce56
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/Data/TaxRuleSearchResultsBuilderTest.php
@@ -0,0 +1,285 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1\Data;
+
+use Magento\Framework\Service\V1\Data\SearchCriteria;
+
+/**
+ * Integration test for \Magento\Tax\Service\V1\Data\TaxRuleSearchResultsBuilder
+ */
+class TaxRuleSearchResultsBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxRuleSearchResults builder
+     *
+     * @var TaxRuleSearchResultsBuilder
+     */
+    private $builder;
+
+    /**
+     * SearchCriteria builder
+     *
+     * @var SearchCriteriaBuilder
+     */
+    private $searchCriteriaBuilder;
+
+    /**
+     * TaxRule builder
+     *
+     * @var TaxRuleBuilder
+     */
+    private $taxRuleBuilder;
+
+    protected function setUp()
+    {
+        $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        $this->builder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleSearchResultsBuilder');
+        $this->searchCriteriaBuilder = $this->objectManager->create(
+            'Magento\Framework\Service\V1\Data\SearchCriteriaBuilder'
+        );
+        $this->taxRuleBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+    }
+
+    /**
+     * @param array $dataArray
+     * @dataProvider createDataProvider
+     */
+    public function testCreateWithPopulateWithArray($dataArray)
+    {
+        $taxRuleSearchResults = $this->builder->populateWithArray($dataArray)->create();
+        $taxRuleSearchResults2 = $this->generateDataObjectWithSetters($dataArray);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRuleSearchResults', $taxRuleSearchResults);
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRuleSearchResults', $taxRuleSearchResults2);
+        $this->assertEquals($taxRuleSearchResults2, $taxRuleSearchResults);
+        $this->assertEquals($dataArray, $taxRuleSearchResults->__toArray());
+        $this->assertEquals($dataArray, $taxRuleSearchResults2->__toArray());
+    }
+
+    public function createDataProvider()
+    {
+
+        $ruleA = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'code',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1, 2],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [3, 4],
+            TaxRule::TAX_RATE_IDS => [1, 3],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $ruleB = [
+            TaxRule::ID => 1,
+            TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        return [
+            [[]],
+            [
+                [
+                    TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                        SearchCriteria::CURRENT_PAGE => 1,
+                        SearchCriteria::PAGE_SIZE => 2,
+                        SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                        SearchCriteria::FILTER_GROUPS => [],
+                    ],
+                    TaxRuleSearchResults::KEY_TOTAL_COUNT => 2,
+                    TaxRuleSearchResults::KEY_ITEMS => [
+                        $ruleA,
+                        $ruleB
+                    ],
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * @param array $dataArray
+     * @param array $zipRangeArray
+     * @dataProvider createDataProvider
+     */
+    public function testPopulate($dataArray)
+    {
+        $taxRuleSearchResults = $this->generateDataObjectWithSetters($dataArray);
+        $taxRuleSearchResults2 = $this->builder->populate($taxRuleSearchResults)->create();
+        $this->assertEquals($taxRuleSearchResults, $taxRuleSearchResults2);
+    }
+
+    public function testMergeDataObjects()
+    {
+        $ruleA = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'code',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1, 2],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [3, 4],
+            TaxRule::TAX_RATE_IDS => [1, 3],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $ruleB = [
+            TaxRule::ID => 1,
+            TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        $data1 =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleA
+            ],
+        ];
+
+        $data2 =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_TOTAL_COUNT => 2,
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleB
+            ],
+        ];
+
+        $dataMerged =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_TOTAL_COUNT => 2,
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleB
+            ],
+        ];
+
+        $taxRuleSearchResults = $this->builder->populateWithArray($dataMerged)->create();
+        $taxRuleSearchResults1 = $this->builder->populateWithArray($data1)->create();
+        $taxRuleSearchResults2 = $this->builder->populateWithArray($data2)->create();
+        $taxRuleSearchResultsMerged = $this->builder->mergeDataObjects($taxRuleSearchResults1, $taxRuleSearchResults2);
+        $this->assertEquals($taxRuleSearchResults->__toArray(), $taxRuleSearchResultsMerged->__toArray());
+    }
+
+    public function testMergeDataObjectWithArray()
+    {
+        $ruleA = [
+            TaxRule::ID => 1,
+            TaxRule::CODE => 'code',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [1, 2],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [3, 4],
+            TaxRule::TAX_RATE_IDS => [1, 3],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => 1,
+        ];
+
+        $ruleB = [
+            TaxRule::ID => 1,
+            TaxRule::TAX_RATE_IDS => [1],
+        ];
+
+        $data1 =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleA
+            ],
+        ];
+
+        $data2 =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_TOTAL_COUNT => 1,
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleB
+            ],
+        ];
+
+        $dataMerged =                 [
+            TaxRuleSearchResults::KEY_SEARCH_CRITERIA => [
+                SearchCriteria::CURRENT_PAGE => 1,
+                SearchCriteria::PAGE_SIZE => 2,
+                SearchCriteria::SORT_ORDERS => SearchCriteria::SORT_DESC,
+                SearchCriteria::FILTER_GROUPS => [],
+            ],
+            TaxRuleSearchResults::KEY_TOTAL_COUNT => 1,
+            TaxRuleSearchResults::KEY_ITEMS => [
+                $ruleB
+            ],
+        ];
+
+        $taxRuleSearchResults = $this->builder->populateWithArray($dataMerged)->create();
+        $taxRuleSearchResults1 = $this->builder->populateWithArray($data1)->create();
+        $taxRuleSearchResultsMerged = $this->builder->mergeDataObjectWithArray($taxRuleSearchResults1, $data2);
+        $this->assertEquals($taxRuleSearchResults->__toArray(), $taxRuleSearchResultsMerged->__toArray());
+    }
+
+    /**
+     * @param array $dataArray
+     * @return TaxRuleSearchResults
+     */
+    protected function generateDataObjectWithSetters($dataArray)
+    {
+        $this->builder->populateWithArray([]);
+        if (array_key_exists(TaxRuleSearchResults::KEY_ITEMS, $dataArray)) {
+            $items = [];
+            foreach ($dataArray[TaxRuleSearchResults::KEY_ITEMS] as $itemArray) {
+                $items[] = $this->taxRuleBuilder->populateWithArray($itemArray)->create();
+            }
+            $this->builder->setItems($items);
+        }
+        if (array_key_exists(TaxRuleSearchResults::KEY_TOTAL_COUNT, $dataArray)) {
+            $this->builder->setTotalCount($dataArray[TaxRuleSearchResults::KEY_TOTAL_COUNT]);
+        }
+        if (array_key_exists(TaxRuleSearchResults::KEY_SEARCH_CRITERIA, $dataArray)) {
+            $this->builder->setSearchCriteria(
+                $this->searchCriteriaBuilder->populateWithArray(
+                    $dataArray[TaxRuleSearchResults::KEY_SEARCH_CRITERIA]
+                )->create()
+            );
+        }
+        return $this->builder->create();
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
new file mode 100644
index 00000000000..146a1c126fe
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxCalculationServiceTest.php
@@ -0,0 +1,1032 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Tax\Model\ClassModel;
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * @magentoDbIsolation enabled
+ */
+class TaxCalculationServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * Tax calculation service
+     *
+     * @var \Magento\Tax\Service\V1\TaxCalculationService
+     */
+    private $taxCalculationService;
+
+    /**
+     * Tax Details Builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetailsBuilder
+     */
+    private $quoteDetailsBuilder;
+
+    /**
+     * Tax Details Item Builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\QuoteDetails\ItemBuilder
+     */
+    private $quoteDetailsItemBuilder;
+
+    /**
+     * Array of default tax classes ids
+     *
+     * Key is class name
+     *
+     * @var int[]
+     */
+    private $taxClasses;
+
+    /**
+     * Array of default tax rates ids.
+     *
+     * Key is rate percentage as string.
+     *
+     * @var int[]
+     */
+    private $taxRates;
+
+    /**
+     * Array of default tax rules ids.
+     *
+     * Key is rule code.
+     *
+     * @var int[]
+     */
+    private $taxRules;
+
+    /**
+     * Helps in creating required tax rules.
+     *
+     * @var TaxRuleFixtureFactory
+     */
+    private $taxRuleFixtureFactory;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->quoteDetailsBuilder = $this->objectManager
+            ->create('Magento\Tax\Service\V1\Data\QuoteDetailsBuilder');
+        $this->quoteDetailsItemBuilder = $this->objectManager
+            ->create('Magento\Tax\Service\V1\data\QuoteDetails\ItemBuilder');
+        $this->taxCalculationService = $this->objectManager->get('\Magento\Tax\Service\V1\TaxCalculationService');
+        $this->taxRuleFixtureFactory = new TaxRuleFixtureFactory();
+
+        $this->setUpDefaultRules();
+    }
+
+    protected function tearDown()
+    {
+        $this->tearDownDefaultRules();
+    }
+
+    /**
+     * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
+     * @dataProvider calculateUnitBasedDataProvider
+     */
+    public function testCalculateTaxUnitBased($quoteDetailsData, $expected)
+    {
+        $quoteDetailsData = $this->performTaxClassSubstitution($quoteDetailsData);
+        $quoteDetails = $this->quoteDetailsBuilder->populateWithArray($quoteDetailsData)->create();
+
+        $taxDetails = $this->taxCalculationService->calculateTax($quoteDetails, 1);
+        $this->assertEquals($expected, $taxDetails->__toArray());
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function calculateUnitBasedDataProvider()
+    {
+        $baseQuote = $this->getBaseQuoteData();
+        $oneProduct = $baseQuote;
+        $oneProduct['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 2,
+            'unit_price' => 10,
+            'tax_class_id' => 'DefaultProductClass',
+        ];
+        $oneProductResults = [
+            'subtotal' => 20,
+            'tax_amount' => 1.5,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'row_tax' => 1.5,
+                    'price' => 10,
+                    'price_incl_tax' => 10.75,
+                    'row_total' => 20,
+                    'taxable_amount' => 10,
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                ],
+            ],
+        ];
+
+        $oneProductInclTax = $baseQuote;
+        $oneProductInclTax['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 2,
+            'unit_price' => 10.75,
+            'row_total' => 21.5,
+            'tax_class_id' => 'DefaultProductClass',
+            'tax_included' => true,
+        ];
+        $oneProductInclTaxResults = $oneProductResults;
+        // TODO: I think this is a bug, but the old code behaved this way so keeping it for now.
+        $oneProductInclTaxResults['items'][0]['taxable_amount'] = 10.75;
+
+        $oneProductInclTaxDiffRate = $baseQuote;
+        $oneProductInclTaxDiffRate['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 2,
+            'unit_price' => 11,
+            'row_total' => 22,
+            'tax_class_id' => 'HigherProductClass',
+            'tax_included' => true,
+        ];
+        $oneProductInclTaxDiffRateResults = [
+            'subtotal' => 20,
+            'tax_amount' => 4.4,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 10,
+                    'price_incl_tax' => 12.2,
+                    'row_total' => 20,
+                    'taxable_amount' => 12.2, // TODO: Possible bug, shouldn't this be 10?
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 22.0,
+                    'row_tax' => 4.4,
+                ],
+            ],
+        ];
+
+        $twoProducts = $baseQuote;
+        $twoProducts['items'] = [
+            [
+                'code' => 'sku_1',
+                'type' => 'product',
+                'quantity' => 2,
+                'unit_price' => 10,
+                'row_total' => 20,
+                'tax_class_id' => 'DefaultProductClass',
+            ],
+            [
+                'code' => 'sku_2',
+                'type' => 'product',
+                'quantity' => 20,
+                'unit_price' => 11,
+                'row_total' => 220,
+                'tax_class_id' => 'DefaultProductClass',
+            ]
+        ];
+        $twoProductsResults = [
+            'subtotal' => 240,
+            'tax_amount' => 18.1,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 10,
+                    'price_incl_tax' => 10.75,
+                    'row_total' => 20,
+                    'taxable_amount' => 10,
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => 1.5,
+                ],
+                [
+                    'price' => 11,
+                    'price_incl_tax' => 11.83,
+                    'row_total' => 220,
+                    'taxable_amount' => 11,
+                    'code' => 'sku_2',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => 16.6,
+                ],
+            ],
+        ];
+
+        $twoProductsInclTax = $baseQuote;
+        $twoProductsInclTax['items'] = [
+            [
+                'code' => 'sku_1',
+                'type' => 'product',
+                'quantity' => 2,
+                'unit_price' => 10.75,
+                'row_total' => 21.5,
+                'tax_class_id' => 'DefaultProductClass',
+                'tax_included' => true,
+            ],
+            [
+                'code' => 'sku_2',
+                'type' => 'product',
+                'quantity' => 20,
+                'unit_price' => 11.83,
+                'row_total' => 236.6,
+                'tax_class_id' => 'DefaultProductClass',
+                'tax_included' => true,
+            ]
+        ];
+        $twoProductInclTaxResults = $twoProductsResults;
+        // TODO: I think this is a bug, but the old code behaved this way so keeping it for now.
+        $twoProductInclTaxResults['items'][0]['taxable_amount'] = 10.75;
+        $twoProductInclTaxResults['items'][1]['taxable_amount'] = 11.83;
+
+        $bundleProduct = $baseQuote;
+        $bundleProduct['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 1,
+            'unit_price' => 10,
+            'row_total' => 10,
+            'tax_class_id' => 'DefaultProductClass',
+            'parent_code' => 'bundle',
+        ];
+        $bundleProduct['items'][] = [
+            'code' => 'bundle',
+            'type' => 'product',
+            'quantity' => 2,
+            'unit_price' => 0,
+            'row_total' => 0,
+            'tax_class_id' => 'DefaultProductClass',
+        ];
+        $bundleProductResults = [
+            'subtotal' => 20,
+            'tax_amount' => 1.5,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'row_tax' => 1.5,
+                    'price' => 10,
+                    'price_incl_tax' => 10.75,
+                    'row_total' => 20,
+                    'taxable_amount' => 10,
+                    'code' => 'bundle',
+                    'type' => 'product',
+                ],
+            ],
+        ];
+
+        return [
+            'one product' => [
+                'quote_details' => $oneProduct,
+                'expected_tax_details' => $oneProductResults,
+            ],
+            'one product, tax included' => [
+                'quote_details' => $oneProductInclTax,
+                'expected_tax_details' => $oneProductInclTaxResults,
+            ],
+            'one product, tax included but differs from store rate' => [
+                'quote_details' => $oneProductInclTaxDiffRate,
+                'expected_tax_details' => $oneProductInclTaxDiffRateResults,
+            ],
+            'two products' => [
+                'quote_details' => $twoProducts,
+                'expected_tax_details' => $twoProductsResults,
+            ],
+            'two products, tax included' => [
+                'quote_details' => $twoProductsInclTax,
+                'expected_tax_details' => $twoProductInclTaxResults,
+            ],
+            'bundle product' => [
+                'quote_details' => $bundleProduct,
+                'expected_tax_details' => $bundleProductResults,
+            ],
+        ];
+    }
+
+    /**
+     * @dataProvider calculateTaxTotalBasedDataProvider
+     * @magentoConfigFixture current_store tax/calculation/algorithm TOTAL_BASE_CALCULATION
+     */
+    public function testCalculateTaxTotalBased($quoteDetailsData, $expectedTaxDetails, $storeId = null)
+    {
+        $quoteDetailsData = $this->performTaxClassSubstitution($quoteDetailsData);
+
+        $quoteDetails = $this->quoteDetailsBuilder->populateWithArray($quoteDetailsData)->create();
+
+        $taxDetails = $this->taxCalculationService->calculateTax($quoteDetails, $storeId);
+
+        $this->assertEquals($expectedTaxDetails, $taxDetails->__toArray());
+    }
+
+    public function calculateTaxTotalBasedDataProvider()
+    {
+        return array_merge(
+            $this->calculateTaxNoTaxInclDataProvider(),
+            $this->calculateTaxTaxInclDataProvider(),
+            $this->calculateTaxRoundingDataProvider()
+        );
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function calculateTaxNoTaxInclDataProvider()
+    {
+        $prodNoTaxInclBase = [
+            'quote_details' => [
+                'shipping_address' => [
+                    'postcode' => '55555',
+                    'country_id' => 'US',
+                    'region' => ['region_id' => 42],
+                ],
+                'items' => [
+                    [
+                        'code' => 'code',
+                        'type' => 'type',
+                        'quantity' => 1,
+                        'unit_price' => 10.0,
+                        'row_total' => 10.0,
+                        'tax_included' => false,
+                    ],
+                ],
+                'customer_tax_class_id' => 'DefaultCustomerClass'
+            ],
+            'expected_tax_details' => [
+                'subtotal' => 10.0,
+                'tax_amount' => 0.0,
+                'discount_amount' => 0.0,
+                'items' => [],
+            ],
+            'store_id' => null,
+        ];
+
+        $prodQuoteDetailItemBase = [
+            'code' => 'code',
+            'type' => 'type',
+            'quantity' => 1,
+            'unit_price' => 10.0,
+            'row_total' => 10.0,
+            'tax_included' => false,
+        ];
+
+        $quoteDetailItemWithDefaultProductTaxClass = $prodQuoteDetailItemBase;
+        $quoteDetailItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+
+        $prodExpectedItemWithNoProductTaxClass = [
+            'row_tax' => 0,
+            'price' => 10.0,
+            'price_incl_tax' => 10.0,
+            'row_total' => 10.0,
+            'taxable_amount' => 10.0,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 0,
+        ];
+
+        $prodExpectedItemWithDefaultProductTaxClass = [
+            'row_tax' => 0.75,
+            'price' => 10.0,
+            'price_incl_tax' => 10.75,
+            'row_total' => 10.0,
+            'taxable_amount' => 10.0,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 7.5,
+        ];
+
+        $prodWithStoreIdWithTaxClassId = $prodNoTaxInclBase;
+        $prodWithStoreIdWithoutTaxClassId = $prodNoTaxInclBase;
+        $prodWithoutStoreIdWithTaxClassId = $prodNoTaxInclBase;
+        $prodWithoutStoreIdWithoutTaxClassId = $prodNoTaxInclBase;
+
+        $prodWithStoreIdWithTaxClassId['store_id'] = 1;
+        $prodWithStoreIdWithTaxClassId['quote_details']['items'][] = $quoteDetailItemWithDefaultProductTaxClass;
+        $prodWithStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 0.75;
+        $prodWithStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithDefaultProductTaxClass;
+
+        $prodWithStoreIdWithoutTaxClassId['store_id'] = 1;
+        $prodWithStoreIdWithoutTaxClassId['quote_details']['items'][] = $prodQuoteDetailItemBase;
+        $prodWithStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithNoProductTaxClass;
+
+        $prodWithoutStoreIdWithTaxClassId['quote_details']['items'][] =
+            $quoteDetailItemWithDefaultProductTaxClass;
+        $prodWithoutStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 0.75;
+        $prodWithoutStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithDefaultProductTaxClass;
+
+        $prodWithoutStoreIdWithoutTaxClassId['quote_details']['items'][] = $prodQuoteDetailItemBase;
+        $prodWithoutStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithNoProductTaxClass;
+
+        return [
+            'product with store id, with tax class id' => $prodWithStoreIdWithTaxClassId,
+            'product with store id, without tax class id' => $prodWithStoreIdWithoutTaxClassId,
+            'product without store id, with tax class id' => $prodWithoutStoreIdWithTaxClassId,
+            'product without store id, without tax class id' => $prodWithoutStoreIdWithoutTaxClassId,
+        ];
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function calculateTaxTaxInclDataProvider()
+    {
+        $productTaxInclBase = [
+            'quote_details' => [
+                'shipping_address' => [
+                    'postcode' => '55555',
+                    'country_id' => 'US',
+                    'region' => ['region_id' => 42],
+                ],
+                'items' => [
+                    [
+                        'code' => 'code',
+                        'type' => 'type',
+                        'quantity' => 1,
+                        'unit_price' => 10.0,
+                        'row_total' => 10.0,
+                        'tax_included' => true,
+                    ],
+                ],
+                'customer_tax_class_id' => 'DefaultCustomerClass'
+            ],
+            'expected_tax_details' => [
+                'subtotal' => 10.0,
+                'tax_amount' => 0.0,
+                'discount_amount' => 0.0,
+                'items' => [],
+            ],
+            'store_id' => null,
+        ];
+
+        $productTaxInclQuoteDetailItemBase = [
+            'code' => 'code',
+            'type' => 'type',
+            'quantity' => 1,
+            'unit_price' => 10.0,
+            'row_total' => 10.0,
+            'tax_included' => true,
+        ];
+
+        $quoteDetailTaxInclItemWithDefaultProductTaxClass = $productTaxInclQuoteDetailItemBase;
+        $quoteDetailTaxInclItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+
+        $productTaxInclExpectedItemWithNoProductTaxClass = [
+            'row_tax' => 0,
+            'price' => 10.0,
+            'price_incl_tax' => 10.0,
+            'row_total' => 10.0,
+            'taxable_amount' => 10.0,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 0,
+        ];
+
+        $productTaxInclExpectedItemWithDefaultProductTaxClass = [
+            'row_tax' => 0.70,
+            'price' => 9.30,
+            'price_incl_tax' => 10.00,
+            'row_total' => 9.30,
+            'taxable_amount' => 9.30,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 7.5,
+        ];
+
+        $productInclTaxWithStoreIdWithTaxClassId = $productTaxInclBase;
+        $productInclTaxWithStoreIdWithoutTaxClassId = $productTaxInclBase;
+        $productInclTaxWithoutStoreIdWithTaxClassId = $productTaxInclBase;
+        $productInclTaxWithoutStoreIdWithoutTaxClassId = $productTaxInclBase;
+
+        $productInclTaxWithStoreIdWithTaxClassId['store_id'] = 1;
+        $productInclTaxWithStoreIdWithTaxClassId['quote_details']['items'][] =
+            $quoteDetailTaxInclItemWithDefaultProductTaxClass;
+        $productInclTaxWithStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 0.70;
+        $productInclTaxWithStoreIdWithTaxClassId['expected_tax_details']['subtotal'] = 9.30;
+        $productInclTaxWithStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $productTaxInclExpectedItemWithDefaultProductTaxClass;
+        $productInclTaxWithStoreIdWithTaxClassId['expected_tax_details']['items'][0]['taxable_amount'] = 10.00;
+
+        $productInclTaxWithStoreIdWithoutTaxClassId['store_id'] = 1;
+        $productInclTaxWithStoreIdWithoutTaxClassId['quote_details']['items'][] =
+            $productTaxInclQuoteDetailItemBase;
+        $productInclTaxWithStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $productTaxInclExpectedItemWithNoProductTaxClass;
+
+        $productInclTaxWithoutStoreIdWithTaxClassId['quote_details']['items'][] =
+            $quoteDetailTaxInclItemWithDefaultProductTaxClass;
+        $productInclTaxWithoutStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 0.70;
+        $productInclTaxWithoutStoreIdWithTaxClassId['expected_tax_details']['subtotal'] = 9.30;
+        $productInclTaxWithoutStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $productTaxInclExpectedItemWithDefaultProductTaxClass;
+        /* TODO: BUG? */
+        $productInclTaxWithoutStoreIdWithTaxClassId['expected_tax_details']['items'][0]['taxable_amount'] = 10.00;
+
+        $productInclTaxWithoutStoreIdWithoutTaxClassId['quote_details']['items'][] = $productTaxInclQuoteDetailItemBase;
+        $productInclTaxWithoutStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $productTaxInclExpectedItemWithNoProductTaxClass;
+
+        return [
+            'product incl tax with store id, with tax class id' => $productInclTaxWithStoreIdWithTaxClassId,
+            'product incl tax with store id, without tax class id' => $productInclTaxWithStoreIdWithoutTaxClassId,
+            'product incl tax without store id, with tax class id' => $productInclTaxWithoutStoreIdWithTaxClassId,
+            'product incl tax without store id, without tax class id' => $productInclTaxWithoutStoreIdWithoutTaxClassId,
+        ];
+    }
+
+    public function calculateTaxRoundingDataProvider()
+    {
+        $prodRoundingNoTaxInclBase = [
+            'quote_details' => [
+                'shipping_address' => [
+                    'postcode' => '55555',
+                    'country_id' => 'US',
+                    'region' => ['region_id' => 42],
+                ],
+                'items' => [
+                    [
+                        'code' => 'code',
+                        'type' => 'type',
+                        'quantity' => 2,
+                        'unit_price' => 7.97,
+                        'row_total' => 15.94,
+                        'tax_included' => false,
+                    ],
+                ],
+                'customer_tax_class_id' => 'DefaultCustomerClass'
+            ],
+            'expected_tax_details' => [
+                'subtotal' => 15.94,
+                'tax_amount' => 0.0,
+                'discount_amount' => 0.0,
+                'items' => [],
+            ],
+            'store_id' => null,
+        ];
+
+        $prodQuoteDetailItemBase = [
+            'code' => 'code',
+            'type' => 'type',
+            'quantity' => 2,
+            'unit_price' => 7.97,
+            'row_total' => 15.94,
+            'tax_included' => false,
+        ];
+
+        $quoteDetailItemWithDefaultProductTaxClass = $prodQuoteDetailItemBase;
+        $quoteDetailItemWithDefaultProductTaxClass['tax_class_id'] = 'DefaultProductClass';
+
+        $prodExpectedItemWithNoProductTaxClass = [
+            'row_tax' => 0,
+            'price' => 7.97,
+            'price_incl_tax' => 7.97,
+            'row_total' => 15.94,
+            'taxable_amount' => 15.94,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 0,
+        ];
+
+        $prodExpectedItemWithDefaultProductTaxClass = [
+            'row_tax' => 1.20,
+            'price' => 7.97,
+            'price_incl_tax' => 8.57,
+            'row_total' => 15.94,
+            'taxable_amount' => 15.94,
+            'code' => 'code',
+            'type' => 'type',
+            'tax_percent' => 7.5,
+        ];
+
+        $prodWithStoreIdWithTaxClassId = $prodRoundingNoTaxInclBase;
+        $prodWithStoreIdWithoutTaxClassId = $prodRoundingNoTaxInclBase;
+        $prodWithoutStoreIdWithTaxClassId = $prodRoundingNoTaxInclBase;
+        $prodWithoutStoreIdWithoutTaxClassId = $prodRoundingNoTaxInclBase;
+
+        $prodWithStoreIdWithTaxClassId['store_id'] = 1;
+        $prodWithStoreIdWithTaxClassId['quote_details']['items'][] = $quoteDetailItemWithDefaultProductTaxClass;
+        $prodWithStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 1.20;
+        $prodWithStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithDefaultProductTaxClass;
+
+        $prodWithStoreIdWithoutTaxClassId['store_id'] = 1;
+        $prodWithStoreIdWithoutTaxClassId['quote_details']['items'][] = $prodQuoteDetailItemBase;
+        $prodWithStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithNoProductTaxClass;
+
+        $prodWithoutStoreIdWithTaxClassId['quote_details']['items'][] =
+            $quoteDetailItemWithDefaultProductTaxClass;
+        $prodWithoutStoreIdWithTaxClassId['expected_tax_details']['tax_amount'] = 1.20;
+        $prodWithoutStoreIdWithTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithDefaultProductTaxClass;
+
+        $prodWithoutStoreIdWithoutTaxClassId['quote_details']['items'][] = $prodQuoteDetailItemBase;
+        $prodWithoutStoreIdWithoutTaxClassId['expected_tax_details']['items'][] =
+            $prodExpectedItemWithNoProductTaxClass;
+
+        return [
+            'rounding product with store id, with tax class id' => $prodWithStoreIdWithTaxClassId,
+            'rounding product with store id, without tax class id' => $prodWithStoreIdWithoutTaxClassId,
+            'rounding product without store id, with tax class id' => $prodWithoutStoreIdWithTaxClassId,
+            'rounding product without store id, without tax class id' => $prodWithoutStoreIdWithoutTaxClassId,
+        ];
+    }
+
+
+    /**
+     * @magentoDbIsolation enabled
+     * @dataProvider calculateTaxRowBasedDataProvider
+     * @magentoConfigFixture default_store tax/calculation/algorithm ROW_BASE_CALCULATION
+     */
+    public function testCalculateTaxRowBased($quoteDetailsData, $expectedTaxDetails)
+    {
+        $quoteDetailsData = $this->performTaxClassSubstitution($quoteDetailsData);
+
+        $quoteDetails = $this->quoteDetailsBuilder->populateWithArray($quoteDetailsData)->create();
+
+        $taxDetails = $this->taxCalculationService->calculateTax($quoteDetails);
+
+        $this->assertEquals($expectedTaxDetails, $taxDetails->__toArray());
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function calculateTaxRowBasedDataProvider()
+    {
+        $baseQuote = $this->getBaseQuoteData();
+        $oneProduct = $baseQuote;
+        $oneProduct['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 10,
+            'unit_price' => 1,
+            'tax_class_id' => 'DefaultProductClass',
+        ];
+        $oneProductResults = [
+            'subtotal' => 10,
+            'tax_amount' => 0.75,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 1,
+                    'price_incl_tax' => 1.08,
+                    'row_total' => 10,
+                    'taxable_amount' => 10,
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => 0.75,
+                ],
+            ],
+        ];
+
+        $oneProductInclTax = $baseQuote;
+        $oneProductInclTax['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 10,
+            'unit_price' => 1.0,
+            'tax_class_id' => 'DefaultProductClass',
+            'tax_included' => true,
+        ];
+        $oneProductInclTaxResults = [
+            'subtotal' => 9.3,
+            'tax_amount' => 0.7,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 0.93,
+                    'price_incl_tax' => 1.0,
+                    'row_total' => 9.3,
+                    'taxable_amount' => 10,  // Shouldn't this be 9.3?
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => .7,
+                ],
+            ],
+        ];
+
+        $oneProductInclTaxDiffRate = $baseQuote;
+        $oneProductInclTaxDiffRate['items'][] = [
+            'code' => 'sku_1',
+            'type' => 'product',
+            'quantity' => 9,
+            'unit_price' => 0.33, // this is including the store tax of 10%. Pre tax is 0.3
+            'tax_class_id' => 'HigherProductClass',
+            'tax_included' => true,
+        ];
+        $oneProductInclTaxDiffRateResults = [
+            'subtotal' => 2.73,
+            'tax_amount' => 0.6,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 0.3,
+                    'price_incl_tax' => 0.37,
+                    'row_total' => 2.73,
+                    'taxable_amount' => 3.33, // Shouldn't this match row_total?
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 22.0,
+                    'row_tax' => 0.6,
+                ],
+            ],
+        ];
+
+        $twoProducts = $baseQuote;
+        $twoProducts['items'] = [
+            [
+                'code' => 'sku_1',
+                'type' => 'product',
+                'quantity' => 10,
+                'unit_price' => 1,
+                'tax_class_id' => 'DefaultProductClass',
+            ],
+            [
+                'code' => 'sku_2',
+                'type' => 'product',
+                'quantity' => 20,
+                'unit_price' => 11,
+                'tax_class_id' => 'DefaultProductClass',
+            ]
+        ];
+        $twoProductsResults = [
+            'subtotal' => 230,
+            'tax_amount' => 17.25,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 1,
+                    'price_incl_tax' => 1.08,
+                    'row_total' => 10,
+                    'taxable_amount' => 10,
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => .75,
+                ],
+                [
+                    'price' => 11,
+                    'price_incl_tax' => 11.83,
+                    'row_total' => 220,
+                    'taxable_amount' => 220,
+                    'code' => 'sku_2',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => 16.5,
+                ],
+            ],
+        ];
+
+        $twoProductsInclTax = $baseQuote;
+        $twoProductsInclTax['items'] = [
+            [
+                'code' => 'sku_1',
+                'type' => 'product',
+                'quantity' => 10,
+                'unit_price' => 0.98,
+                'tax_class_id' => 'DefaultProductClass',
+                'tax_included' => true,
+            ],
+            [
+                'code' => 'sku_2',
+                'type' => 'product',
+                'quantity' => 20,
+                'unit_price' => 11.99,
+                'tax_class_id' => 'DefaultProductClass',
+                'tax_included' => true,
+            ]
+        ];
+        $twoProductInclTaxResults = [
+            'subtotal' => 232.19,
+            'tax_amount' => 17.41,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'price' => 0.91,
+                    'price_incl_tax' => 0.98,
+                    'row_total' => 9.12,
+                    'taxable_amount' => 9.8,  // Shouldn't this match row_total?
+                    'code' => 'sku_1',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => .68,
+                ],
+                [
+                    'price' => 11.15,
+                    'price_incl_tax' => 11.99,
+                    'row_total' => 223.07,
+                    'taxable_amount' => 239.8, // Shouldn't this be 223.07?
+                    'code' => 'sku_2',
+                    'type' => 'product',
+                    'tax_percent' => 7.5,
+                    'row_tax' => 16.73,
+                ],
+            ],
+        ];
+
+        $oneProductWithChildren = $baseQuote;
+        $oneProductWithChildren['items'] = [
+            [
+                'code' => 'child_1_sku',
+                'type' => 'product',
+                'quantity' => 2,
+                'unit_price' => 12.34,
+                'tax_class_id' => 'DefaultProductClass',
+                'parent_code' => 'parent_sku',
+            ],
+            [
+                'code' => 'parent_sku', // Put the parent in the middle of the children to test an edge case
+                'type' => 'product',
+                'quantity' => 10,
+                'unit_price' => 0,
+                'tax_class_id' => 'DefaultProductClass',
+            ],
+            [
+                'code' => 'child_2_sku',
+                'type' => 'product',
+                'quantity' => 2,
+                'unit_price' => 1.99,
+                'tax_class_id' => 'HigherProductClass',
+                'parent_code' => 'parent_sku',
+            ],
+        ];
+        $oneProductWithChildrenResults = [
+            'subtotal' => 286.6,
+            'tax_amount' => 27.27,
+            'discount_amount' => 0,
+            'items' => [
+                [
+                    'code' => 'parent_sku',
+                    'price' => 28.66,
+                    'price_incl_tax' => 31.39,
+                    'row_total' => 286.6,
+                    'taxable_amount' => 286.6,
+                    'type' => 'product',
+                    'row_tax' => 27.27,
+                ],
+            ],
+        ];
+
+        return [
+            'one product' => [
+                'quote_details' => $oneProduct,
+                'expected_tax_details' => $oneProductResults,
+            ],
+            'one product, tax included' => [
+                'quote_details' => $oneProductInclTax,
+                'expected_tax_details' => $oneProductInclTaxResults,
+            ],
+            'one product, tax included but differs from store rate' => [
+                'quote_details' => $oneProductInclTaxDiffRate,
+                'expected_tax_details' => $oneProductInclTaxDiffRateResults,
+            ],
+            'two products' => [
+                'quote_details' => $twoProducts,
+                'expected_tax_details' => $twoProductsResults,
+            ],
+            'two products, tax included' => [
+                'quote_details' => $twoProductsInclTax,
+                'expected_tax_details' => $twoProductInclTaxResults,
+            ],
+            'one product with two children' => [
+                'quote_details' => $oneProductWithChildren,
+                'expected_tax_details' => $oneProductWithChildrenResults,
+            ],
+        ];
+    }
+
+    /**
+     * Substitutes an ID for the name of a tax class in a tax class ID field.
+     *
+     * @param array $data
+     * @return array
+     */
+    private function performTaxClassSubstitution($data)
+    {
+        array_walk_recursive(
+            $data,
+            function (&$value, $key) {
+                if ( ($key === 'tax_class_id' || $key === 'customer_tax_class_id')
+                    && is_string($value)
+                ) {
+                    $value = $this->taxClasses[$value];
+                }
+            }
+        );
+
+        return $data;
+    }
+
+    /**
+     * Helper function that sets up some default rules
+     */
+    private function setUpDefaultRules()
+    {
+        $this->taxClasses = $this->taxRuleFixtureFactory->createTaxClasses([
+            ['name' => 'DefaultCustomerClass', 'type' => ClassModel::TAX_CLASS_TYPE_CUSTOMER],
+            ['name' => 'DefaultProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+            ['name' => 'HigherProductClass', 'type' => ClassModel::TAX_CLASS_TYPE_PRODUCT],
+        ]);
+
+        $this->taxRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 7.5, 'country' => 'US', 'region' => 42],
+            ['percentage' => 7.5, 'country' => 'US', 'region' => 12], // Default store rate
+        ]);
+
+        $higherRates = $this->taxRuleFixtureFactory->createTaxRates([
+            ['percentage' => 22, 'country' => 'US', 'region' => 42],
+            ['percentage' => 10, 'country' => 'US', 'region' => 12], // Default store rate
+            ]);
+
+        $this->taxRules = $this->taxRuleFixtureFactory->createTaxRules([
+            [
+                'code' => 'Default Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['DefaultProductClass']],
+                'tax_rate_ids' => array_values($this->taxRates),
+                'sort_order' => 0,
+                'priority' => 0,
+            ],
+            [
+                'code' => 'Higher Rate Rule',
+                'customer_tax_class_ids' => [$this->taxClasses['DefaultCustomerClass'], 3],
+                'product_tax_class_ids' => [$this->taxClasses['HigherProductClass']],
+                'tax_rate_ids' => array_values($higherRates),
+                'sort_order' => 0,
+                'priority' => 0,
+            ],
+        ]);
+
+        // For cleanup
+        $this->taxRates = array_merge($this->taxRates, $higherRates);
+    }
+
+    /**
+     * Helper function that tears down some default rules
+     */
+    private function tearDownDefaultRules()
+    {
+        $this->taxRuleFixtureFactory->deleteTaxRules(array_values($this->taxRules));
+        $this->taxRuleFixtureFactory->deleteTaxRates(array_values($this->taxRates));
+        $this->taxRuleFixtureFactory->deleteTaxClasses(array_values($this->taxClasses));
+    }
+
+    /**
+     * @return array
+     */
+    private function getBaseQuoteData()
+    {
+        $baseQuote = [
+            'billing_address' => [
+                'postcode' => '55555',
+                'country_id' => 'US',
+                'region' => ['region_id' => 42],
+            ],
+            'shipping_address' => [
+                'postcode' => '55555',
+                'country_id' => 'US',
+                'region' => ['region_id' => 42],
+            ],
+            'items' => [],
+            'customer_tax_class_id' => 'DefaultCustomerClass',
+        ];
+        return $baseQuote;
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
new file mode 100644
index 00000000000..501206c328b
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
@@ -0,0 +1,345 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Tax\Service\V1\Data\ZipRangeBuilder;
+use Magento\TestFramework\Helper\Bootstrap;
+
+class TaxRateServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxRate builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxRateBuilder
+     */
+    private $taxRateBuilder;
+
+    /**
+     * TaxRateService
+     *
+     * @var \Magento\Tax\Service\V1\TaxRateServiceInterface
+     */
+    private $taxRateService;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->taxRateService = $this->objectManager->get('Magento\Tax\Service\V1\TaxRateServiceInterface');
+        $this->taxRateBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testCreateTaxRate()
+    {
+        $taxData = [
+            'country_id' => 'US',
+            'region_id' => '8',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate' . rand(),
+            'zip_range' => ['from' => 78765, 'to' => 78780]
+        ];
+        // Tax rate data object created
+        $taxRate = $this->taxRateBuilder->populateWithArray($taxData)->create();
+        //Tax rate service call
+        $taxRateServiceData = $this->taxRateService->createTaxRate($taxRate);
+
+        //Assertions
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRate', $taxRateServiceData);
+        $this->assertEquals($taxData['country_id'], $taxRateServiceData->getCountryId());
+        $this->assertEquals($taxData['region_id'], $taxRateServiceData->getRegionId());
+        $this->assertEquals($taxData['percentage_rate'], $taxRateServiceData->getPercentageRate());
+        $this->assertEquals($taxData['code'], $taxRateServiceData->getCode());
+        $this->assertEquals($taxData['region_id'], $taxRateServiceData->getRegionId());
+        $this->assertEquals($taxData['percentage_rate'], $taxRateServiceData->getPercentageRate());
+        $this->assertEquals($taxData['zip_range']['from'], $taxRateServiceData->getZipRange()->getFrom());
+        $this->assertEquals($taxData['zip_range']['to'], $taxRateServiceData->getZipRange()->getTo());
+        $this->assertEquals('78765-78780', $taxRateServiceData->getPostcode());
+        $this->assertNotNull($taxRateServiceData->getId());
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     * @expectedExceptionMessage Code already exists.
+     * @magentoDbIsolation enabled
+     */
+    public function testCreateTaxRateDuplicateCodes()
+    {
+        $invalidTaxData = [
+            'country_id' => 'US',
+            'region_id' => '8',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate' . rand(),
+            'zip_range' => ['from' => 78765, 'to' => 78780]
+        ];
+        $taxRate = $this->taxRateBuilder->populateWithArray($invalidTaxData)->create();
+        //Service call initiated twice to add the same code
+        $this->taxRateService->createTaxRate($taxRate);
+        $this->taxRateService->createTaxRate($taxRate);
+    }
+
+    /**
+     * @param array $dataArray
+     * @param string $errorMessages
+     * @throws \Magento\Framework\Exception\InputException
+     *
+     * @dataProvider createDataProvider
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @magentoDbIsolation enabled
+     */
+    public function testCreateTaxRateWithExceptionMessages($dataArray, $errorMessages)
+    {
+        $expectedErrorMessages = [
+            'country_id is a required field.',
+            'region_id is a required field.',
+            'percentage_rate is a required field.',
+            'code is a required field.'
+        ];
+        $expectedErrorMessages = array_merge($expectedErrorMessages, $errorMessages);
+        $taxRate = $this->taxRateBuilder->populateWithArray($dataArray)->create();
+        try {
+            $this->taxRateService->createTaxRate($taxRate);
+        } catch (InputException $exception) {
+            $errors = $exception->getErrors();
+            foreach ($errors as $key => $error) {
+                $this->assertEquals($expectedErrorMessages[$key], $error->getMessage());
+            }
+            throw $exception;
+        }
+    }
+
+    public function createDataProvider()
+    {
+        return [
+            'invalidZipRange' => [
+                ['zip_range' => ['from' => 'from', 'to' => 'to']],
+                'error' => [
+                    'Invalid value of "from" provided for the zip_from field.',
+                    'Invalid value of "to" provided for the zip_to field.'
+                ]
+            ],
+            'emptyZipRange' => [
+                ['zip_range' => ['from' => '', 'to' => '']],
+                'error' => [
+                    'Invalid value of "" provided for the zip_from field.',
+                    'Invalid value of "" provided for the zip_to field.'
+                ]
+            ],
+            'empty' => [
+                [],
+                'error' => ['postcode is a required field.']
+            ],
+            'zipRangeAndPostcode' => [
+                ['postcode' => 78727, 'zip_range' => ['from' => 78765, 'to' => 78780]],
+                'error' => []
+            ],
+            'higherRange' => [
+                ['zip_range' => ['from' => 78780, 'to' => 78765]],
+                'error' => ['Range To should be equal or greater than Range From.']
+            ]
+        ];
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testGetTaxRate()
+    {
+        $data = [
+            'tax_country_id' => 'US',
+            'tax_region_id' => '12',
+            'tax_postcode' => '*',
+            'code' => 'US_12_Code',
+            'rate' => '7.5'
+        ];
+        $rate = $this->objectManager->create('Magento\Tax\Model\Calculation\Rate')
+            ->setData($data)
+            ->save();
+
+        $taxRate = $this->taxRateService->getTaxRate($rate->getId());
+
+        $this->assertEquals('US', $taxRate->getCountryId());
+        $this->assertEquals(12, $taxRate->getRegionId());
+        $this->assertEquals('*', $taxRate->getPostcode());
+        $this->assertEquals('US_12_Code', $taxRate->getCode());
+        $this->assertEquals(7.5, $taxRate->getPercentageRate());
+        $this->assertNull($taxRate->getZipRange());
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage No such entity with taxRateId = -1
+     */
+    public function testGetRateWithNoSuchEntityException()
+    {
+        $this->taxRateService->getTaxRate(-1);
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testUpdateTaxRates()
+    {
+        /** @var ZipRangeBuilder $zipRangeBuilder */
+        $zipRangeBuilder = $this->objectManager->get('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        $taxRate = $this->taxRateBuilder
+            ->setCountryId('US')
+            ->setRegionId(42)
+            ->setPercentageRate(8.25)
+            ->setCode('UpdateTaxRates')
+            ->setPostcode('78780')
+            ->create();
+        $taxRate = $this->taxRateService->createTaxRate($taxRate);
+        $zipRange = $zipRangeBuilder->setFrom(78700)->setTo(78780)->create();
+        $updatedTaxRate = $this->taxRateBuilder->populate($taxRate)
+            ->setPostcode(null)
+            ->setZipRange($zipRange)
+            ->create();
+
+        $this->taxRateService->updateTaxRate($updatedTaxRate);
+
+        $retrievedRate = $this->taxRateService->getTaxRate($taxRate->getId());
+        // Expect the service to have filled in the new postcode for us
+        $updatedTaxRate = $this->taxRateBuilder->populate($updatedTaxRate)->setPostcode('78700-78780')->create();
+        $this->assertEquals($retrievedRate->__toArray(), $updatedTaxRate->__toArray());
+        $this->assertNotEquals($retrievedRate->__toArray(), $taxRate->__toArray());
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage taxRateId =
+     */
+    public function testUpdateTaxRateNoId()
+    {
+        $taxRate = $this->taxRateBuilder
+            ->setCountryId('US')
+            ->setRegionId(42)
+            ->setPercentageRate(8.25)
+            ->setCode('UpdateTaxRates')
+            ->setPostcode('78780')
+            ->create();
+
+        $this->taxRateService->updateTaxRate($taxRate);
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @expectedExceptionMessage postcode
+     */
+    public function testUpdateTaxRateMissingRequiredFields()
+    {
+        $taxRate = $this->taxRateBuilder
+            ->setCountryId('US')
+            ->setRegionId(42)
+            ->setPercentageRate(8.25)
+            ->setCode('UpdateTaxRates')
+            ->setPostcode('78780')
+            ->create();
+        $taxRate = $this->taxRateService->createTaxRate($taxRate);
+        $updatedTaxRate = $this->taxRateBuilder->populate($taxRate)
+            ->setPostcode(null)
+            ->create();
+
+        $this->taxRateService->updateTaxRate($updatedTaxRate);
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testDeleteTaxRate()
+    {
+        // Create a new tax rate
+        $taxRateData = $this->taxRateBuilder
+            ->setCode('TX')
+            ->setCountryId('US')
+            ->setPercentageRate(5)
+            ->setPostcode(77000)
+            ->setRegionId(1)
+            ->create();
+        $taxRateId = $this->taxRateService->createTaxRate($taxRateData)->getId();
+
+        // Delete the new tax rate
+        $this->assertTrue($this->taxRateService->deleteTaxRate($taxRateId));
+
+        // Get the new tax rate, this should fail
+        try {
+            $this->taxRateService->getTaxRate($taxRateId);
+            $this->fail('NoSuchEntityException expected but not thrown');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRateId',
+                'fieldValue' => $taxRateId,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        } catch (\Exception $e) {
+            $this->fail('Caught unexpected exception');
+        }
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testDeleteTaxRateException()
+    {
+        // Create a new tax rate
+        $taxRateData = $this->taxRateBuilder
+            ->setCode('TX')
+            ->setCountryId('US')
+            ->setPercentageRate(6)
+            ->setPostcode(77001)
+            ->setRegionId(1)
+            ->create();
+        $taxRateId = $this->taxRateService->createTaxRate($taxRateData)->getId();
+
+        // Delete the new tax rate
+        $this->assertTrue($this->taxRateService->deleteTaxRate($taxRateId));
+
+        // Delete the new tax rate again, this should fail
+        try {
+            $this->taxRateService->deleteTaxRate($taxRateId);
+            $this->fail('NoSuchEntityException expected but not thrown');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRateId',
+                'fieldValue' => $taxRateId,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        } catch (\Exception $e) {
+            $this->fail('Caught unexpected exception');
+        }
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleFixtureFactory.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleFixtureFactory.php
new file mode 100644
index 00000000000..c1cea6aba29
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleFixtureFactory.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * TaxRuleFixtureFactory is meant to help in testing tax by creating/destroying tax rules/classes/rates easily.
+ */
+class TaxRuleFixtureFactory
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    public function __construct()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+    }
+
+    /**
+     * Helper to create tax rules.
+     *
+     * @param array $rulesData Keys match TaxRuleBuilder populateWithArray
+     * @return array code => rule id
+     */
+    public function createTaxRules($rulesData)
+    {
+        /** @var \Magento\Tax\Service\V1\Data\TaxRuleBuilder $taxRuleBuilder */
+        $taxRuleBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        /** @var \Magento\Tax\Service\V1\TaxRuleServiceInterface $taxRuleService */
+        $taxRuleService = $this->objectManager->create('Magento\Tax\Service\V1\TaxRuleServiceInterface');
+
+        $rules = [];
+        foreach ($rulesData as $ruleData) {
+            $taxRuleBuilder->populateWithArray($ruleData);
+
+            $rules[$ruleData['code']] = $taxRuleService->createTaxRule($taxRuleBuilder->create())->getId();
+        }
+
+        return $rules;
+    }
+
+    /**
+     * Helper function that deletes tax rules
+     *
+     * @param int[] $ruleIds
+     */
+    public function deleteTaxRules($ruleIds)
+    {
+        /** @var \Magento\Tax\Service\V1\TaxRuleServiceInterface $taxRuleService */
+        $taxRuleService = $this->objectManager->create('Magento\Tax\Service\V1\TaxRuleServiceInterface');
+
+        foreach ($ruleIds as $ruleId) {
+            $taxRuleService->deleteTaxRule($ruleId);
+        }
+    }
+
+    /**
+     * Helper function that creates rates based on a set of input percentages.
+     *
+     * Returns a map of percentage => rate
+     *
+     * @param array $ratesData array of rate data, keys are 'country', 'region' and 'percentage'
+     * @return int[] Tax Rate Id
+     */
+    public function createTaxRates($ratesData)
+    {
+
+        /** @var \Magento\Tax\Service\V1\Data\TaxRateBuilder $taxRateBuilder */
+        $taxRateBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        /** @var \Magento\Tax\Service\V1\TaxRateServiceInterface $taxRateService */
+        $taxRateService = $this->objectManager->create('Magento\Tax\Service\V1\TaxRateServiceInterface');
+
+        $rates = [];
+        foreach ($ratesData as $rateData) {
+            $code = "{$rateData['country']} - {$rateData['region']} - {$rateData['percentage']}";
+            $taxRateBuilder->setCountryId($rateData['country'])
+                ->setRegionId($rateData['region'])
+                ->setPostcode('*')
+                ->setCode($code)
+                ->setPercentageRate($rateData['percentage']);
+
+            $rates[$code] =
+                $taxRateService->createTaxRate($taxRateBuilder->create())->getId();
+        }
+        return $rates;
+    }
+
+    /**
+     * Helper function that deletes tax rates
+     *
+     * @param int[] $rateIds
+     */
+    public function deleteTaxRates($rateIds)
+    {
+        /** @var \Magento\Tax\Service\V1\TaxRateServiceInterface $taxRateService */
+        $taxRateService = $this->objectManager->create('Magento\Tax\Service\V1\TaxRateServiceInterface');
+        foreach ($rateIds as $rateId) {
+            $taxRateService->deleteTaxRate($rateId);
+        }
+    }
+
+    /**
+     * Helper function that creates tax classes based on input.
+     *
+     * @param array $classesData Keys include 'name' and 'type'
+     * @return array ClassName => ClassId
+     */
+    public function createTaxClasses($classesData)
+    {
+        $classes = [];
+        foreach ($classesData as $classData) {
+            /** @var \Magento\Tax\Model\ClassModel $class */
+            $class = $this->objectManager->create('Magento\Tax\Model\ClassModel')
+                ->setClassName($classData['name'])
+                ->setClassType($classData['type'])
+                ->save();
+            $classes[$classData['name']] = $class->getId();
+        }
+        return $classes;
+    }
+
+    /**
+     * Helper function that deletes tax classes
+     *
+     * @param int[] $classIds
+     */
+    public function deleteTaxClasses($classIds)
+    {
+        /** @var \Magento\Tax\Model\ClassModel $class */
+        $class = $this->objectManager->create('Magento\Tax\Model\ClassModel');
+        foreach ($classIds as $classId) {
+            $class->setId($classId);
+            $class->delete();
+        }
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
new file mode 100644
index 00000000000..859726da03a
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
@@ -0,0 +1,279 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Service\V1;
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Tax\Service\V1\Data\TaxRule;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Exception\InputException;
+
+/**
+ * Class TaxRuleServiceTest tests Magento/Tax/Service/V1/TaxRuleService
+ *
+ */
+class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Object Manager
+     *
+     * @var \Magento\Framework\ObjectManager
+     */
+    private $objectManager;
+
+    /**
+     * TaxRule builder
+     *
+     * @var \Magento\Tax\Service\V1\Data\TaxRuleBuilder
+     */
+    private $taxRuleBuilder;
+
+    /**
+     * TaxRuleService
+     *
+     * @var \Magento\Tax\Service\V1\TaxRuleServiceInterface
+     */
+    private $taxRuleService;
+
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->taxRuleService = $this->objectManager->get('Magento\Tax\Service\V1\TaxRuleServiceInterface');
+        $this->taxRuleBuilder = $this->objectManager->create('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testCreateTaxRule()
+    {
+        // Tax rule data object created
+        $taxRuleDataObject = $this->createTaxRuleDataObject();
+        //Tax rule service call
+        $taxRuleServiceData = $this->taxRuleService->createTaxRule($taxRuleDataObject);
+
+        //Assertions
+        $this->assertInstanceOf('\Magento\Tax\Service\V1\Data\TaxRule', $taxRuleServiceData);
+        $this->assertEquals($taxRuleDataObject->getCode(), $taxRuleServiceData->getCode());
+        $this->assertEquals(
+            $taxRuleDataObject->getCustomerTaxClassIds(),
+            $taxRuleServiceData->getCustomerTaxClassIds()
+        );
+        $this->assertEquals($taxRuleDataObject->getProductTaxClassIds(), $taxRuleServiceData->getProductTaxClassIds());
+        $this->assertEquals($taxRuleDataObject->getPriority(), $taxRuleServiceData->getPriority());
+        $this->assertEquals($taxRuleDataObject->getSortOrder(), $taxRuleServiceData->getSortOrder());
+        $this->assertNotNull($taxRuleServiceData->getId());
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testCreateTaxRuleInvalid()
+    {
+        $taxRuleData = [
+            TaxRule::CODE => 'code',
+            TaxRule::CUSTOMER_TAX_CLASS_IDS => [3],
+            TaxRule::PRODUCT_TAX_CLASS_IDS => [2],
+            TaxRule::TAX_RATE_IDS => [1],
+            TaxRule::PRIORITY => 0,
+            TaxRule::SORT_ORDER => -1,
+        ];
+        // Tax rule data object created
+        $taxRule = $this->taxRuleBuilder->populateWithArray($taxRuleData)->create();
+
+        try {
+            //Tax rule service call
+            $this->taxRuleService->createTaxRule($taxRule);
+            $this->fail('Did not throw expected InputException');
+        } catch (InputException $e) {
+            $expectedParams = [
+                'fieldName' => taxRule::SORT_ORDER,
+                'value' => -1,
+                'minValue' => '0',
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+            $this->assertEquals(InputException::INVALID_FIELD_MIN_VALUE, $e->getRawMessage());
+        }
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testGetTaxRuleCreatedFromService()
+    {
+        // Tax rule data object created
+        $taxRuleDataObject = $this->createTaxRuleDataObject();
+        //Tax rule service call to create rule
+        $ruleId = $this->taxRuleService->createTaxRule($taxRuleDataObject)->getId();
+
+        // Call getTaxRule and verify
+        $taxRule = $this->taxRuleService->getTaxRule($ruleId);
+        $this->assertEquals('code', $taxRule->getCode());
+        $this->assertEquals([3], $taxRule->getCustomerTaxClassIds());
+        $this->assertEquals([2], $taxRule->getProductTaxClassIds());
+        $this->assertEquals([2], $taxRule->getTaxRateIds());
+        $this->assertEquals(0, $taxRule->getPriority());
+        $this->assertEquals(1, $taxRule->getSortOrder());
+    }
+    /**
+     * @magentoDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testGetTaxRuleCreatedFromModel()
+    {
+        /** @var $registry \Magento\Framework\Registry */
+        $registry = $this->objectManager->get('Magento\Framework\Registry');
+        /** @var $taxRuleModel \Magento\Tax\Model\Calculation\Rule */
+        $taxRuleModel = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
+        $this->assertNotNull($taxRuleModel);
+        $ruleId = $taxRuleModel->getId();
+
+        $taxRateId = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rate')->getId();
+        $customerTaxClassIds = array_unique($taxRuleModel->getCustomerTaxClasses());
+
+        // Call getTaxRule and verify
+        $taxRule = $this->taxRuleService->getTaxRule($ruleId);
+        $this->assertEquals($customerTaxClassIds, $taxRule->getCustomerTaxClassIds());
+        $this->assertEquals([$taxRateId], $taxRule->getTaxRateIds());
+    }
+
+    /**
+     * @magentoDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testDeleteTaxRule()
+    {
+        /** @var $registry \Magento\Framework\Registry */
+        $registry = $this->objectManager->get('Magento\Framework\Registry');
+        /** @var $taxRule \Magento\Tax\Model\Calculation\Rule */
+        $taxRule = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
+        $this->assertNotNull($taxRule);
+        $ruleId = $taxRule->getId();
+
+        // Delete the new tax rate
+        $this->assertTrue($this->taxRuleService->deleteTaxRule($ruleId));
+
+        // Get the new tax rule, this should fail
+        try {
+            $this->taxRuleService->getTaxRule($ruleId);
+            $this->fail('NoSuchEntityException expected but not thrown');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRuleId',
+                'fieldValue' => $ruleId,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        }
+    }
+
+    /**
+     * @magentoDataFixture Magento/Tax/_files/tax_classes.php
+     */
+    public function testDeleteTaxRateException()
+    {
+        /** @var $registry \Magento\Framework\Registry */
+        $registry = $this->objectManager->get('Magento\Framework\Registry');
+        /** @var $taxRule \Magento\Tax\Model\Calculation\Rule */
+        $taxRule = $registry->registry('_fixture/Magento_Tax_Model_Calculation_Rule');
+        $this->assertNotNull($taxRule);
+        $ruleId = $taxRule->getId();
+
+        // Delete the new tax rate
+        $this->assertTrue($this->taxRuleService->deleteTaxRule($ruleId));
+
+        // Delete the new tax rate again, this should fail
+        try {
+            $this->taxRuleService->deleteTaxRule($ruleId);
+            $this->fail('NoSuchEntityException expected but not thrown');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRuleId',
+                'fieldValue' => $ruleId,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        }
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     */
+    public function testUpdateTaxRule()
+    {
+
+        $taxRule = $this->createTaxRuleDataObject();
+        //Tax rule service call
+        $taxRuleServiceData = $this->taxRuleService->createTaxRule($taxRule);
+
+        $updatedTaxRule = $this->taxRuleBuilder->populate($taxRuleServiceData)
+            ->setCode('updated code')
+            ->create();
+
+        $this->taxRuleService->updateTaxRule($updatedTaxRule);
+        $retrievedRule = $this->taxRuleService->getTaxRule($taxRuleServiceData->getId());
+
+        //Assertion
+        $this->assertEquals($updatedTaxRule->__toArray(), $retrievedRule->__toArray());
+        $this->assertNotEquals($taxRule->__toArray(), $retrievedRule->__toArray());
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage taxRuleId =
+     */
+    public function testUpdateTaxRuleNoId()
+    {
+        $this->taxRuleService->updateTaxRule($this->createTaxRuleDataObject());
+    }
+
+    /**
+     * @magentoDbIsolation enabled
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @expectedExceptionMessage code
+     */
+    public function testUpdateTaxRuleMissingRequiredFields()
+    {
+        $taxRuleServiceData = $this->taxRuleService->createTaxRule($this->createTaxRuleDataObject());
+        $updatedTaxRule = $this->taxRuleBuilder->populate($taxRuleServiceData)
+            ->setCode(null)
+            ->create();
+
+        $this->taxRuleService->updateTaxRule($updatedTaxRule);
+    }
+
+    /**
+     * Creates Tax Rule Data Object
+     *
+     * @return \Magento\Tax\Service\V1\Data\TaxRule
+     */
+    private function createTaxRuleDataObject()
+    {
+        return $this->taxRuleBuilder
+            ->setCode('code')
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes.php
index c3690ad7078..b1333b330db 100644
--- a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes.php
+++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes.php
@@ -65,7 +65,10 @@ $taxRate = array(
 );
 $rate = $objectManager->create('Magento\Tax\Model\Calculation\Rate')->setData($taxRate)->save();
 
-$objectManager->get('Magento\Framework\Registry')->register('_fixture/Magento_Tax_Model_Calculation_Rate', $rate);
+/** @var Magento\Framework\Registry $registry */
+$registry = $objectManager->get('Magento\Framework\Registry');
+$registry->unregister('_fixture/Magento_Tax_Model_Calculation_Rate');
+$registry->register('_fixture/Magento_Tax_Model_Calculation_Rate', $rate);
 
 $ruleData = array(
     'code' => 'Test Rule',
@@ -78,7 +81,8 @@ $ruleData = array(
 
 $taxRule = $objectManager->create('Magento\Tax\Model\Calculation\Rule')->setData($ruleData)->save();
 
-$objectManager->get('Magento\Framework\Registry')->register('_fixture/Magento_Tax_Model_Calculation_Rule', $taxRule);
+$registry->unregister('_fixture/Magento_Tax_Model_Calculation_Rule');
+$registry->register('_fixture/Magento_Tax_Model_Calculation_Rule', $taxRule);
 
 $ruleData['code'] = 'Test Rule Duplicate';
 
diff --git a/dev/tests/integration/testsuite/Magento/User/Model/RulesTest.php b/dev/tests/integration/testsuite/Magento/User/Model/RulesTest.php
index 39f89e9bceb..fd6271449ae 100644
--- a/dev/tests/integration/testsuite/Magento/User/Model/RulesTest.php
+++ b/dev/tests/integration/testsuite/Magento/User/Model/RulesTest.php
@@ -45,19 +45,13 @@ class RulesTest extends \PHPUnit_Framework_TestCase
      */
     public function testCRUD()
     {
-        $this->_model->setRoleType(
-            'G'
-        )->setResourceId(
-            'Magento_Adminhtml::all'
-        )->setPrivileges(
-            ""
-        )->setAssertId(
-            0
-        )->setRoleId(
-            1
-        )->setPermission(
-            'allow'
-        );
+        $this->_model
+            ->setRoleType('G')
+            ->setResourceId('Magento_Adminhtml::all')
+            ->setPrivileges("")
+            ->setAssertId(0)
+            ->setRoleId(1)
+            ->setPermission('allow');
 
         $crud = new \Magento\TestFramework\Entity($this->_model, array('permission' => 'deny'));
         $crud->testCrud();
@@ -68,14 +62,8 @@ class RulesTest extends \PHPUnit_Framework_TestCase
      */
     public function testInitialUserPermissions()
     {
-        $adapter = $this->_model->getResource()->getReadConnection();
-        $ruleSelect = $adapter->select()->from($this->_model->getResource()->getMainTable());
-
-        $rules = $ruleSelect->query()->fetchAll();
-        $this->assertEquals(1, count($rules));
-        $this->assertEquals('Magento_Adminhtml::all', $rules[0]['resource_id']);
-        $this->assertEquals(1, $rules[0]['role_id']);
-        $this->assertEquals('allow', $rules[0]['permission']);
+        $expectedDefaultPermissions = ['Magento_Adminhtml::all'];
+        $this->_checkExistingPermissions($expectedDefaultPermissions);
     }
 
     /**
@@ -84,17 +72,31 @@ class RulesTest extends \PHPUnit_Framework_TestCase
      */
     public function testSetAllowForAllResources()
     {
-        $adapter = $this->_model->getResource()->getReadConnection();
-        $ruleSelect = $adapter->select()->from($this->_model->getResource()->getMainTable());
-
         $resources = array('Magento_Adminhtml::all');
-
         $this->_model->setRoleId(1)->setResources($resources)->saveRel();
+        $expectedPermissions = ['Magento_Adminhtml::all'];
+        $this->_checkExistingPermissions($expectedPermissions);
+    }
+
+    /**
+     * Ensure that only expected permissions are set.
+     */
+    protected function _checkExistingPermissions($expectedDefaultPermissions)
+    {
+        $adapter = $this->_model->getResource()->getReadConnection();
+        $ruleSelect = $adapter->select()->from($this->_model->getResource()->getMainTable());
 
         $rules = $ruleSelect->query()->fetchAll();
         $this->assertEquals(1, count($rules));
-        $this->assertEquals('Magento_Adminhtml::all', $rules[0]['resource_id']);
-        $this->assertEquals(1, $rules[0]['role_id']);
-        $this->assertEquals('allow', $rules[0]['permission']);
+        $actualPermissions = [];
+        foreach ($rules as $rule) {
+            $actualPermissions[] = $rule['resource_id'];
+            $this->assertEquals(
+                'allow',
+                $rule['permission'],
+                "Permission for '{$rule['resource_id']}' resource should be 'allow'"
+            );
+        }
+        $this->assertEquals($expectedDefaultPermissions, $actualPermissions, 'Default permissions are invalid');
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
index 66227bf9c83..6664082c8d6 100644
--- a/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
+++ b/dev/tests/integration/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
@@ -26,13 +26,17 @@ return [
         'Magento\TestModule1\Service\V1\AllSoapAndRestInterface' => [
             'item' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
+                    0 => [
+                        'Magento_Test1::resource1'
+                    ]
                 ],
                 'secure' => false,
             ],
             'create' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
+                    0 => [
+                        'Magento_Test1::resource1'
+                    ]
                 ],
                 'secure' => false,
             ],
@@ -40,29 +44,37 @@ return [
         'Magento\TestModule1\Service\V2\AllSoapAndRestInterface' => [
             'item' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
-                    'Magento_Test1::resource2' => true,
+                    0 => [
+                        'Magento_Test1::resource1',
+                        'Magento_Test1::resource2'
+                    ]
                 ],
                 'secure' => false,
             ],
             'create' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
-                    'Magento_Test1::resource2' => true,
+                    0 => [
+                        'Magento_Test1::resource1',
+                        'Magento_Test1::resource2'
+                    ]
                 ],
                 'secure' => false,
             ],
             'delete' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
-                    'Magento_Test1::resource2' => true,
+                    0 => [
+                        'Magento_Test1::resource1',
+                        'Magento_Test1::resource2'
+                    ]
                 ],
                 'secure' => false,
             ],
             'update' => [
                 'resources' => [
-                    'Magento_Test1::resource1' => true,
-                    'Magento_Test1::resource2' => true,
+                    0 => [
+                        'Magento_Test1::resource1',
+                        'Magento_Test1::resource2'
+                    ]
                 ],
                 'secure' => false,
             ],
diff --git a/dev/tests/integration/testsuite/Magento/Widget/Model/Config/_files/code/Magento/Test/etc/module.xml b/dev/tests/integration/testsuite/Magento/Widget/Model/Config/_files/code/Magento/Test/etc/module.xml
index 63aa7da0ace..ee1d7873ab8 100644
--- a/dev/tests/integration/testsuite/Magento/Widget/Model/Config/_files/code/Magento/Test/etc/module.xml
+++ b/dev/tests/integration/testsuite/Magento/Widget/Model/Config/_files/code/Magento/Test/etc/module.xml
@@ -24,5 +24,5 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Magento_Test" version="1.11.0.1" active="true" />
+    <module name="Magento_Test" schema_version="1.11.0.1" active="true" />
 </config>
diff --git a/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/theme.xml b/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/theme.xml
index 80b272c2dc3..caed16ca902 100644
--- a/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/theme.xml
+++ b/dev/tests/integration/testsuite/Magento/Widget/_files/design/adminhtml/magento_basic/theme.xml
@@ -24,5 +24,5 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Basic</title>
-    <version>2.0.0.0</version>
+    <version>0.1.0</version>
 </theme>
diff --git a/dev/tests/js/testsuite/mage/validation/test-validation.js b/dev/tests/js/testsuite/mage/validation/test-validation.js
index ce803dd47e1..5f3258896db 100644
--- a/dev/tests/js/testsuite/mage/validation/test-validation.js
+++ b/dev/tests/js/testsuite/mage/validation/test-validation.js
@@ -524,3 +524,48 @@ test( "testValidateCCCvn", function() {
     ok($.validator.methods['validate-cc-cvn'].call(this, '123', null, ccType));
     ok(!$.validator.methods['validate-cc-cvn'].call(this, '1234', null, ccType));
 });
+
+test( "testValidateNumberRange", function() {
+    expect(14);
+    ok($.validator.methods['validate-number-range'].call(this, '-1', null, null));
+    ok($.validator.methods['validate-number-range'].call(this, '1', null, null));
+    ok($.validator.methods['validate-number-range'].call(this, '', null, null));
+    ok($.validator.methods['validate-number-range'].call(this, null, null, null));
+    ok($.validator.methods['validate-number-range'].call(this, '0', null, null));
+    ok(!$.validator.methods['validate-number-range'].call(this, 'asds', null, null));
+
+    ok($.validator.methods['validate-number-range'].call(this, '10', null, '10-20.06'));
+    ok($.validator.methods['validate-number-range'].call(this, '15', null, '10-20.06'));
+    ok(!$.validator.methods['validate-number-range'].call(this, '1', null, '10-20.06'));
+    ok(!$.validator.methods['validate-number-range'].call(this, '30', null, '10-20.06'));
+
+    var el1 = $('<input type="text" value="" class="validate-number-range number-range-10-20 number-range-10-100.20">').get(0);
+    ok($.validator.methods['validate-number-range'].call(this, '10', el1, null));
+    ok($.validator.methods['validate-number-range'].call(this, '15', el1, null));
+    ok(!$.validator.methods['validate-number-range'].call(this, '1', el1, null));
+    ok($.validator.methods['validate-number-range'].call(this, '30', el1, null));
+});
+
+
+
+test( "testValidateDigitsRange", function() {
+    expect(15);
+    ok($.validator.methods['validate-digits-range'].call(this, '-1', null, null));
+    ok($.validator.methods['validate-digits-range'].call(this, '1', null, null));
+    ok($.validator.methods['validate-digits-range'].call(this, '', null, null));
+    ok($.validator.methods['validate-digits-range'].call(this, null, null, null));
+    ok($.validator.methods['validate-digits-range'].call(this, '0', null, null));
+    ok(!$.validator.methods['validate-digits-range'].call(this, 'asds', null, null));
+
+    ok($.validator.methods['validate-digits-range'].call(this, '10', null, '10-20'));
+    ok($.validator.methods['validate-digits-range'].call(this, '15', null, '10-20'));
+    ok(!$.validator.methods['validate-digits-range'].call(this, '1', null, '10-20'));
+    ok(!$.validator.methods['validate-digits-range'].call(this, '30', null, '10-20'));
+    ok($.validator.methods['validate-digits-range'].call(this, '30', null, '10-20.06'));
+
+    var el1 = $('<input type="text" value="" class="validate-digits-range digits-range-10-20 digits-range-10-100.20">').get(0);
+    ok($.validator.methods['validate-digits-range'].call(this, '10', el1, null));
+    ok($.validator.methods['validate-digits-range'].call(this, '15', el1, null));
+    ok(!$.validator.methods['validate-digits-range'].call(this, '1', el1, null));
+    ok(!$.validator.methods['validate-digits-range'].call(this, '30', el1, null));
+});
\ No newline at end of file
diff --git a/dev/tests/performance/framework/Magento/TestFramework/Helper/Categories.php b/dev/tests/performance/framework/Magento/TestFramework/Helper/Categories.php
index 05ec1d432cd..b648f5a0af6 100644
--- a/dev/tests/performance/framework/Magento/TestFramework/Helper/Categories.php
+++ b/dev/tests/performance/framework/Magento/TestFramework/Helper/Categories.php
@@ -72,7 +72,7 @@ class Categories
         /**
          * Preapre categories paths for import
          *
-         * @see \Magento\ImportExport\Model\Import\Entity\Product::_initCategories()
+         * @see \Magento\CatalogImportExport\Model\Import\Product::_initCategories()
          */
         foreach ($categories as $key => $categoryId) {
             $category->load($categoryId);
diff --git a/dev/tests/static/framework/Magento/TestFramework/Integrity/AbstractConfig.php b/dev/tests/static/framework/Magento/TestFramework/Integrity/AbstractConfig.php
index 23c938721ee..cda2ebb23a4 100644
--- a/dev/tests/static/framework/Magento/TestFramework/Integrity/AbstractConfig.php
+++ b/dev/tests/static/framework/Magento/TestFramework/Integrity/AbstractConfig.php
@@ -29,6 +29,9 @@ abstract class AbstractConfig extends \PHPUnit_Framework_TestCase
 {
     public function testXmlFiles()
     {
+        if (null === $this->_getXmlName()) {
+            $this->markTestSkipped('No XML validation of files requested');
+        }
         $invoker = new \Magento\TestFramework\Utility\AggregateInvoker($this);
         $invoker(
             /**
diff --git a/dev/tests/static/phpunit.xml.dist b/dev/tests/static/phpunit.xml.dist
index 148c8beb330..6a58c9aaf01 100644
--- a/dev/tests/static/phpunit.xml.dist
+++ b/dev/tests/static/phpunit.xml.dist
@@ -41,5 +41,7 @@
         <ini name="date.timezone" value="America/Los_Angeles"/>
         <!-- TESTS_JSHINT_PATH specify the path to wsh.js on Windows and jshint-rhino.js on Linux -->
         <const name="TESTS_JSHINT_PATH" value=""/>
+        <!-- TESTS_COMPOSER_PATH - specify the path to composer binary, if a relative reference cannot be resolved -->
+        <!--<const name="TESTS_COMPOSER_PATH" value="/usr/local/bin/composer"/>-->
     </php>
 </phpunit>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
new file mode 100644
index 00000000000..f36bad617a1
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/ConfigTest.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Test\Integrity\App\Language;
+
+class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig
+{
+    public function testSchemaUsingInvalidXml($expectedErrors = null)
+    {
+        $expectedErrors = array(
+            "Element 'code': [facet 'pattern'] The value 'e_GB' is not accepted by the pattern",
+            "Element 'code': 'e_GB' is not a valid value of the atomic type 'codeType'",
+            "Element 'vendor': [facet 'pattern'] The value 'agento' is not accepted by the pattern",
+            "Element 'vendor': 'agento' is not a valid value of the atomic type",
+            "Element 'sort_odrer': This element is not expected. Expected is one of",
+        );
+        parent::testSchemaUsingInvalidXml($expectedErrors);
+    }
+
+    /**
+     * Returns the name of the XSD file to be used to validate the XML
+     *
+     * @return string
+     */
+    protected function _getXsd()
+    {
+        return '/lib/internal/Magento/Framework/App/Language/package.xsd';
+    }
+
+    /**
+     * The location of a single valid complete xml file
+     *
+     * @return string
+     */
+    protected function _getKnownValidXml()
+    {
+        return __DIR__ . '/_files/known_valid.xml';
+    }
+
+    /**
+     * The location of a single known invalid complete xml file
+     *
+     * @return string
+     */
+    protected function _getKnownInvalidXml()
+    {
+        return __DIR__ . '/_files/known_invalid.xml';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _getKnownValidPartialXml()
+    {
+        return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _getFileXsd()
+    {
+        return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _getKnownInvalidPartialXml()
+    {
+        return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _getXmlName()
+    {
+        return;
+    }
+}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
new file mode 100644
index 00000000000..86d812bcebf
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/PackageTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Test\Integrity\App\Language;
+
+/**
+ * A test for language package declaration
+ */
+class PackageTest extends \PHPUnit_Framework_TestCase
+{
+    public function testExistingFilesDeclared()
+    {
+        $root = \Magento\TestFramework\Utility\Files::init()->getPathToSource();
+        $notDeclared = array_diff($this->getLangsFromCsvFiles($root), $this->getDeclaredLangs($root));
+        $print = print_r($notDeclared, true);
+        $this->assertEmpty(
+            $notDeclared,
+            "There are .csv files in the system that are not declared by any of the language package: {$print}"
+        );
+    }
+
+    /**
+     * Scan code base for .csv files in the expected location of translations and determine distinct list of languages
+     *
+     * @param string $rootDir
+     * @return array
+     */
+    private function getLangsFromCsvFiles($rootDir)
+    {
+        $result = [];
+        foreach (glob("{$rootDir}/app/{code/*/*,design/*/*/*}/i18n/*.csv", GLOB_BRACE) as $file) {
+            $lang = preg_replace('/\.csv$/i', '', basename($file));
+            $result[$lang] = $lang;
+        }
+        return $result;
+    }
+
+    /**
+     * Scan code base for language.xml files and figure out distinct list of languages from their file structure
+     *
+     * @param string $rootDir
+     * @return array
+     */
+    private function getDeclaredLangs($rootDir)
+    {
+        $result = [];
+        foreach (self::readDeclarationFiles($rootDir) as $row) {
+            $result[$row[2]] = $row[2];
+        }
+        return $result;
+    }
+
+    /**
+     * @param string $file
+     * @param string $expectedVendor
+     * @param string $expectedCode
+     * @dataProvider declaredConsistentlyDataProvider
+     */
+    public function testDeclaredConsistently($file, $expectedVendor, $expectedCode)
+    {
+        $dom = new \DOMDocument();
+        $dom->load($file);
+        $root = $dom->documentElement;
+        \Magento\Framework\App\Language\Dictionary::assertVendor($expectedVendor, $root);
+        \Magento\Framework\App\Language\Dictionary::assertCode($expectedCode, $root);
+    }
+
+    /**
+     * @return array
+     */
+    public function declaredConsistentlyDataProvider()
+    {
+        $result = [];
+        $root = \Magento\TestFramework\Utility\Files::init()->getPathToSource();
+        foreach (self::readDeclarationFiles($root) as $row) {
+            $result[] = $row;
+        }
+        return $result;
+    }
+
+    /**
+     * Read all lamguage.xml files and figure out the vendor and language code according from the file structure
+     *
+     * @param string $rootDir
+     * @return array
+     */
+    private static function readDeclarationFiles($rootDir)
+    {
+        $result = [];
+        foreach (glob("{$rootDir}/app/i18n/*/*/language.xml") as $file) {
+            preg_match('/.+\/(.*)\/(.*)\/language.xml$/', $file, $matches);
+            $matches[0] = $file;
+            $result[] = $matches;
+        }
+        return $result;
+    }
+}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
new file mode 100644
index 00000000000..9366bbeedcf
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_invalid.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>e_GB</code>
+    <vendor>agento</vendor>
+    <sort_odrer>100</sort_odrer>
+    <use code="en_GB"/>
+</language>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
new file mode 100644
index 00000000000..d13de1dd866
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/_files/known_valid.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/App/Language/package.xsd">
+    <code>en_GB</code>
+    <vendor>Magento</vendor>
+    <sort_order>100</sort_order>
+    <use vendor="OxfordUniversity" code="en_GB"/>
+</language>
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ConfigTest.php
index 535d806be02..1f3938c1eed 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/ConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ConfigTest.php
@@ -25,44 +25,6 @@ namespace Magento\Test\Integrity;
 
 class ConfigTest extends \PHPUnit_Framework_TestCase
 {
-    protected $_possibleLocales = array(
-        'de_DE',
-        'en_AU',
-        'en_GB',
-        'en_US',
-        'es_ES',
-        'es_XC',
-        'fr_FR',
-        'fr_XC',
-        'it_IT',
-        'ja_JP',
-        'nl_NL',
-        'pl_PL',
-        'zh_CN',
-        'zh_XC',
-        'pt_BR'
-    );
-
-    public function testExistingFilesDeclared()
-    {
-        $root = \Magento\TestFramework\Utility\Files::init()->getPathToSource();
-        $failures = array();
-        foreach (glob("{$root}/app/code/*/*", GLOB_ONLYDIR) as $modulePath) {
-            $localeFiles = glob("{$modulePath}/i18n/*.csv");
-            foreach ($localeFiles as $file) {
-                $file = realpath($file);
-                $assertLocale = str_replace('.csv', '', basename($file));
-                if (!in_array($assertLocale, $this->_possibleLocales)) {
-                    $failures[] = $file;
-                }
-            }
-        }
-        $this->assertEmpty(
-            $failures,
-            'Translation files exist, but not declared in configuration:' . "\n" . var_export($failures, 1)
-        );
-    }
-
     public function testPaymentMethods()
     {
         $invoker = new \Magento\TestFramework\Utility\AggregateInvoker($this);
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php
index 8aaa14f1516..fc5744bfbab 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Webapi/Model/ConfigTest.php
@@ -37,8 +37,6 @@ class ConfigTest extends AbstractConfig
             "Element 'route', attribute 'method': [facet 'enumeration'] The value 'PATCH' is not an element of the set {'GET', 'PUT', 'POST', 'DELETE'}.",
             "Element 'route', attribute 'method': 'PATCH' is not a valid value of the local atomic type.",
             "Element 'service': The attribute 'method' is required but missing.",
-            "Element 'resource', attribute 'ref': [facet 'pattern'] The value 'a resource' is not accepted by the pattern '.+::.+(, ?.+::.+)*'.",
-            "Element 'resource', attribute 'ref': 'a resource' is not a valid value of the local atomic type.",
             "Element 'data': Missing child element(s). Expected is ( parameter ).",
             "Element 'route': Missing child element(s). Expected is ( service ).",
             "Element 'route': Missing child element(s). Expected is ( resources ).",
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/PageType/FilesTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/PageType/FilesTest.php
deleted file mode 100644
index 041aebd54d7..00000000000
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/PageType/FilesTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Test\Integrity\PageType;
-
-class FilesTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var string - xsd that will validate page_types.xml against
-     */
-    protected $_schemaFile;
-
-    protected function setUp()
-    {
-        $this->_schemaFile = \Magento\TestFramework\Utility\Files::init()->getModuleFile(
-            'Magento',
-            'Core',
-            'etc/page_types.xsd'
-        );
-    }
-
-    public function testPageType()
-    {
-        $invoker = new \Magento\TestFramework\Utility\AggregateInvoker($this);
-        $invoker(
-            function ($pageType) {
-                $dom = new \DOMDocument();
-                $dom->loadXML(file_get_contents($pageType));
-                $errors = \Magento\TestFramework\Utility\Validator::validateXml($dom, $this->_schemaFile);
-                $this->assertTrue(empty($errors), print_r($errors, true));
-            },
-            \Magento\TestFramework\Utility\Files::init()->getPageTypeFiles()
-        );
-    }
-}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php
index 5fde03ebc31..a02aead7976 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php
@@ -36,7 +36,7 @@ class SchemaTest extends \PHPUnit_Framework_TestCase
         $xmlFile = file_get_contents($filename);
         $dom->loadXML($xmlFile);
         $errors = libxml_get_errors();
-        $this->assertTrue(empty($errors), print_r($errors, true));
+        $this->assertEmpty($errors, print_r($errors, true));
 
         $schemaLocations = [];
         preg_match('/xsi:noNamespaceSchemaLocation=\s*"([^"]+)"/s', $xmlFile, $schemaLocations);
@@ -53,9 +53,8 @@ xsi:noNamespaceSchemaLocation="../../../lib/internal/Magento/Framework/etc/somet
 
         $this->assertTrue(file_exists($schemaFile), "$filename refers to an invalid schema $schemaFile.");
 
-        $this->assertTrue($dom->schemaValidate($schemaFile), "$filename doesn't validate against $schemaFile");
-        $errors = libxml_get_errors();
-        $this->assertTrue(empty($errors), "Error validating $filename against $schemaFile\n" . print_r($errors, true));
+        $errors = \Magento\TestFramework\Utility\Validator::validateXml($dom, $schemaFile);
+        $this->assertEmpty($errors, "Error validating $filename against $schemaFile\n" . print_r($errors, true));
     }
 
 
@@ -68,13 +67,8 @@ xsi:noNamespaceSchemaLocation="../../../lib/internal/Magento/Framework/etc/somet
 
     public function getXmlFiles()
     {
-        $codeXml = $this->_getFiles(BP . '/app/code/Magento', '*.xml');
-        $codeXml = array_filter(
-            $codeXml,
-            function ($item) {
-                return strpos($item, "Dhl/etc/countries.xml") == false;
-            }
-        );
+        $codeXml = $this->_getFiles(BP . '/app', '*.xml');
+        $this->_filterSpecialCases($codeXml);
         $designXml = $this->_getFiles(BP . '/app/design', '*.xml');
         $libXml = $this->_getFiles(BP . '/lib/Magento', '*.xml');
         return $this->_dataSet(array_merge($codeXml, $designXml, $libXml));
@@ -89,6 +83,27 @@ xsi:noNamespaceSchemaLocation="../../../lib/internal/Magento/Framework/etc/somet
         return $files;
     }
 
+    /**
+     * Files that are exempt from validation
+     *
+     * @param array &$files
+     */
+    private function _filterSpecialCases(&$files)
+    {
+        $list = [
+            '#Dhl/etc/countries.xml$#',
+            '#app/etc/local.xml$#',
+            '#app/etc/[a-z]+/module.xml$#'
+        ];
+        foreach ($list as $pattern) {
+            foreach ($files as $key => $value) {
+                if (preg_match($pattern, $value)) {
+                    unset($files[$key]);
+                }
+            }
+        }
+    }
+
     protected function _dataSet($files)
     {
         $arrayWrap = function ($item) {
@@ -96,14 +111,4 @@ xsi:noNamespaceSchemaLocation="../../../lib/internal/Magento/Framework/etc/somet
         };
         return array_combine($files, array_map($arrayWrap, $files));
     }
-
-    public function _getSchemaKey($schemaFilename)
-    {
-        $key = $schemaFilename;
-        $index = strpos($schemaFilename, "Magento");
-        if ($index) {
-            $key = substr($schemaFilename, $index);
-        }
-        return $key;
-    }
 }
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/Module/ModuleXMLTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/Module/ModuleXMLTest.php
new file mode 100644
index 00000000000..cf71745a1ff
--- /dev/null
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/Magento/Framework/Module/ModuleXMLTest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright  Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Test\Legacy\Magento\Framework\Module;
+
+/**
+ * Test for obsolete nodes/attributes in the module.xml
+ */
+class ModuleXMLTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @param string $file
+     * @dataProvider moduleXmlDataProvider
+     */
+    public function testModuleXml($file)
+    {
+        $xml = simplexml_load_file($file);
+        $this->assertEmpty(
+            $xml->xpath('/config/module/@version'),
+            'The "version" attribute is obsolete. Use "schema_version" instead.'
+        );
+    }
+
+    /**
+     * @return array
+     */
+    public function moduleXmlDataProvider()
+    {
+        return \Magento\TestFramework\Utility\Files::init()->getConfigFiles('module.xml');
+    }
+}
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 f8bffc780f1..79cc3706905 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
@@ -1964,11 +1964,19 @@ return array(
     ),
     array(
         'Magento\ImportExport\Model\Export\Entity\Product\Type\Grouped',
-        'Magento\GroupedProduct\Model\Export\Entity\Product\Type\Grouped'
+        'Magento\CatalogImportExport\Model\Export\Entity\Product\Type\Grouped'
     ),
     array(
         'Magento\ImportExport\Model\Import\Entity\Product\Type\Grouped',
-        'Magento\GroupedProduct\Model\Import\Entity\Product\Type\Grouped'
+        'Magento\CatalogImportExport\Model\Import\Entity\Product\Type\Grouped'
+    ),
+    array(
+        'Magento\GroupedProduct\Model\Export\Entity\Product\Type\Grouped',
+        'Magento\CatalogImportExport\Model\Export\Entity\Product\Type\Grouped'
+    ),
+    array(
+        'Magento\GroupedProduct\Model\Import\Entity\Product\Type\Grouped',
+        'Magento\CatalogImportExport\Model\Import\Entity\Product\Type\Grouped'
     ),
     array('CollFactory', 'CollectionFactory'), // no need to shorten anymore
     array(
@@ -2063,11 +2071,19 @@ return array(
     ),
     array(
         'Magento\ImportExport\Model\Export\Entity\Product\Type\Configurable',
-        'Magento\ConfigurableProduct\Model\Export\Entity\Product\Type\Configurable'
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Configurable'
+    ),
+    array(
+        'Magento\ConfigurableProduct\Model\Export\Entity\Product\Type\Configurable',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Configurable'
     ),
     array(
         'Magento\ImportExport\Model\Import\Entity\Product\Type\Configurable',
-        'Magento\ConfigurableProduct\Model\Import\Entity\Product\Type\Configurable'
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Configurable'
+    ),
+    array(
+        'Magento\ConfigurableProduct\Model\Import\Entity\Product\Type\Configurable',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Configurable'
     ),
     array('Magento\Sales\Block\Adminhtml\Items\Renderer\Configurable'),
     array(
@@ -2108,19 +2124,11 @@ return array(
         'Magento\Framework\Locale\Resolver, Magento\Framework\Locale\Currency, Magento\Framework\Locale\Format, ' .
         'Magento\Framework\Stdlib\DateTime\Timezone, Magento\Framework\Locale\Lists'
     ),
-    array(
-        'Magento\Core\Model\Locale\Hierarchy\Config\Converter',
-        'Magento\Framework\Locale\Hierarchy\Config\Converter'
-    ),
-    array(
-        'Magento\Core\Model\Locale\Hierarchy\Config\FileResolver',
-        'Magento\Framework\Locale\Hierarchy\Config\FileResolver'
-    ),
-    array('Magento\Core\Model\Locale\Hierarchy\Config\Reader', 'Magento\Framework\Locale\Hierarchy\Config\Reader'),
-    array(
-        'Magento\Core\Model\Locale\Hierarchy\Config\SchemaLocator',
-        'Magento\Framework\Locale\Hierarchy\Config\SchemaLocator'
-    ),
+    array('Magento\Framework\Locale\Hierarchy\Config\Converter', 'Magento\Framework\App\Language\Dictionary'),
+    array('Magento\Framework\Locale\Hierarchy\Config\FileResolver', 'Magento\Framework\App\Language\Dictionary'),
+    array('Magento\Framework\Locale\Hierarchy\Config\Reader', 'Magento\Framework\App\Language\Dictionary'),
+    array('Magento\Framework\Locale\Hierarchy\Config\SchemaLocator', 'Magento\Framework\App\Language\Dictionary'),
+    array('Magento\Framework\Locale\Hierarchy\Config', 'Magento\Framework\App\Language\Dictionary'),
     array('Magento\Core\Model\Locale\Config', 'Magento\Framework\Locale\Config'),
     array('Magento\Core\Model\Locale\Validator', 'Magento\Framework\Locale\Validator'),
     array('Magento\Core\Model\Date', 'Magento\Framework\Stdlib\DateTime\DateTime'),
@@ -2449,6 +2457,72 @@ return array(
     ['Magento\Phrase', 'Magento\Framework\Phrase'],
     ['Magento\Pear', 'Magento\Framework\Pear'],
     ['Magento\Connect\Channel\Generator', 'Magento\Framework\Connect\Channel\Generator'],
+    [
+        'Magento\ImportExport\Model\Export\Product\Type\AbstractType',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Product\Type\Factory',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Factory'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Product\Type\Simple',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Simple'
+    ],
+    ['Magento\ImportExport\Model\Export\Product', 'Magento\CatalogImportExport\Model\Export\Product'],
+    [
+        'Magento\ImportExport\Model\Export\RowCustomizer\Composite',
+        'Magento\CatalogImportExport\Model\Export\RowCustomizer\Composite'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\RowCustomizerInterface',
+        'Magento\CatalogImportExport\Model\Export\RowCustomizerInterface'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Product\Type\AbstractType',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Product\Type\Factory',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Factory'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Product\Type\Simple',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Simple'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Product\Option',
+        'Magento\CatalogImportExport\Model\Import\Product\Option'
+    ],
+    ['Magento\ImportExport\Model\Import\Product', 'Magento\CatalogImportExport\Model\Import\Product'],
+    [
+        'Magento\ImportExport\Model\Import\Proxy\Product',
+        'Magento\CatalogImportExport\Model\Import\Proxy\Product'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Proxy\Product\Resource',
+        'Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Uploader',
+        'Magento\CatalogImportExport\Model\Import\Uploader'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Entity\Customer\Finance',
+        'Magento\CustomerFinance\Model\Export\Customer\Finance'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Eav\Customer\Finance',
+        'Magento\CustomerFinance\Model\Import\Entity\Eav\Customer\Finance'
+    ],
+    [
+        'Magento\ImportExport\Model\Resource\Customer\Attribute\Finance\Collection',
+        'Magento\CustomerFinance\Model\Resource\Customer\Attribute\Finance\Collection'
+    ],
+    [
+        'Magento\ImportExport\Model\Resource\Customer\Collection',
+        'Magento\CustomerFinance\Model\Resource\Customer\Collection'
+    ],
     ['Magento\Connect\Channel\VO', 'Magento\Framework\Connect\Channel\VO'],
     ['Magento\Connect\Command\Channels', 'Magento\Framework\Connect\Command\Channels'],
     ['Magento\Connect\Command\Config', 'Magento\Framework\Connect\Command\Config'],
@@ -2554,6 +2628,7 @@ return array(
         'Magento\DesignEditor\Block\Adminhtml\Editor\Tools\Code\Css\Group',
         'Magento\DesignEditor\Block\Adminhtml\Editor\Tools\Code\Css'
     ],
+    ['Magento\Framework\Filter\GridArray\Grid'],
     ['Magento\Css\PreProcessor\Composite'],
     ['Magento\Css\PreProcessor\UrlResolver', 'Magento\Framework\View\Asset\PreProcessor\ModuleNotation'],
     ['Magento\Less\PreProcessor\File\FileList'],
@@ -2586,9 +2661,46 @@ return array(
     ['Magento\Css\PreProcessor\Cache\CacheInterface'],
     ['Magento\Css\PreProcessor\Cache\CacheManager'],
     ['Magento\Framework\View\Design\FileResolution\Strategy\ViewInterface'],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Product',
+        'Magento\CatalogImportExport\Model\Import\Product'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Product\Option',
+        'Magento\CatalogImportExport\Model\Import\Product\Option'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Product\Type\Factory',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Factory'
+    ],
+    [
+        'Magento\ImportExport\Model\Import\Entity\Product\Type\Simple',
+        'Magento\CatalogImportExport\Model\Import\Product\Type\Simple'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Entity\Product',
+        'Magento\CatalogImportExport\Model\Export\Product'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Entity\Product\Type\Factory',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Factory'
+    ],
+    [
+        'Magento\ImportExport\Model\Export\Entity\Product\Type\Simple',
+        'Magento\CatalogImportExport\Model\Export\Product\Type\Simple'
+    ],
     [
         'Magento\Bundle\Pricing\Price\BasePrice',
         'Magento\Catalog\Pricing\Price\BasePrice'
     ],
     ['\Magento\Bundle\Pricing\Price\BasePriceInterface'],
+    ['\Magento\Paypal\Block\PayflowExpress\Shortcut']
 );
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 3784f405985..cd8801dbfbc 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
@@ -59,6 +59,7 @@ return array(
         'Magento\Store\Model\StorageFactory::_checkRequestStore'),
     array('_checkUrlSettings', 'Magento\Backend\Controller\Adminhtml\Action'),
     array('_collectOrigData', 'Magento\Catalog\Model\Resource\AbstractResource'),
+    array('_decodeFilter', 'Magento\Backend\Block\Widget\Grid'),
     array('_decodeInput', 'Magento\Catalog\Controller\Adminhtml\Product'),
     array('_emailOrderConfirmation', 'Magento\Checkout\Model\Type\AbstractType'),
     array('_escapeValue', 'Magento\Backend\Block\Widget\Grid\Column\Filter\AbstractFilter'),
@@ -152,8 +153,8 @@ return array(
     array('_parsePackageTheme', 'Magento\Widget\Model\Widget\Instance'),
     array('_parseXmlTrackingResponse', 'Magento\Fedex\Model\Carrier'),
     array('_prepareCondition', 'Magento\CatalogSearch\Model\Advanced'),
-    array('_prepareConfigurableProductData', 'Magento\ImportExport\Model\Export\Entity\Product'),
-    array('_prepareConfigurableProductPrice', 'Magento\ImportExport\Model\Export\Entity\Product'),
+    array('_prepareConfigurableProductData', 'Magento\CatalogImportExport\Model\Export\Product'),
+    array('_prepareConfigurableProductPrice', 'Magento\CatalogImportExport\Model\Export\Product'),
     array(
         '_prepareLastRecurringProfiles()',
         'Magento\Checkout\Block\Onepage\Success',
@@ -330,6 +331,7 @@ return array(
     array('createEntityTables', 'Magento\Eav\Model\Entity\Setup'),
     array('createOrderItem', 'Magento\CatalogInventory\Model\Observer'),
     array('debugRequest', 'Magento\Paypal\Model\Api\Standard'),
+    array('decodeFilter', 'Magento\Backend\Helper\Data'),
     array('decorateArray', 'Magento\Core\Helper\Data', 'Magento\Framework\Stdlib\ArrayUtils::decorateArray'),
     array('deleteAction', 'Magento\Catalog\Controller\Adminhtml\Product'),
     array('deleteConfig', 'Magento\Core\Model\Config'),
@@ -350,6 +352,26 @@ return array(
     array('flush', 'Magento\Framework\App\Cache', 'Magento_Cache_FrontendInterface::clean()'),
     array('flush', 'Magento\Framework\App\Cache\Proxy', 'Magento_Cache_FrontendInterface::clean()'),
     array('flush', 'Magento\Framework\App\CacheInterface', 'Magento_Cache_FrontendInterface::clean()'),
+    array(
+        'getProductTypes',
+        'Magento\ImportExport\Model\Import\Config',
+        'Magento\ImportExport\Model\Import\Config::getEntityTypes()'
+    ),
+    array(
+        'getProductTypes',
+        '\Magento\ImportExport\Model\Import\ConfigInterface',
+        '\Magento\ImportExport\Model\Import\ConfigInterface::getEntityTypes()'
+    ),
+    array(
+        'getProductTypes',
+        'Magento\ImportExport\Model\Export\Config',
+        'Magento\ImportExport\Model\Export\Config::getEntityTypes()'
+    ),
+    array(
+        'getProductTypes',
+        '\Magento\ImportExport\Model\Export\ConfigInterface',
+        '\Magento\ImportExport\Model\Export\ConfigInterface::getEntityTypes()'
+    ),
     array('forsedSave'),
     array('generateBlocks', '', 'generateElements()'),
     array('getAbsolutePath', '', 'normalizePath'),
@@ -731,7 +753,7 @@ return array(
     array('postDispatchMyAccountSave'),
     array('postDispatchSystemImportExportRun'),
     array('prepareAddressInfo', 'Magento\Sales\Block\Recurring\Profile\View'),
-    array('prepareAttributesForSave', 'Magento\ImportExport\Model\Import\Entity\Product'),
+    array('prepareAttributesForSave', 'Magento\CatalogImportExport\Model\Import\Product'),
     array('prepareFeesInfo', 'Magento\Sales\Block\Recurring\Profile\View'),
     array('prepareGoogleOptimizerScripts'),
     array('prepareRedirect', 'Magento\Core\Controller\Varien\Exception'),
@@ -996,6 +1018,7 @@ return array(
     array('getProductStatusModel', 'Magento\CatalogInventory\Model\Stock\Status'),
     array('getStorage', 'Magento\Cms\Helper\Wysiwyg\Images'),
     array('_getSession', 'Magento\Review\Helper\Action\Pager'),
+    array('expandSource', 'Magento\ImportExport\Model\Import'),
     array('_getProductType', 'Magento\Backend\Block\Catalog\Product\Edit\Tab\Super\Config\Matrix'),
     array('_getProductType', 'Magento\Backend\Block\Catalog\Product\Edit\Tab\Super\Config'),
     array('_getSession', 'Magento\Sales\Model\AdminOrder'),
@@ -1721,6 +1744,9 @@ return array(
         'Magento\Framework\View\Asset\ModuleNotation\Resolver::convertModuleNotationToPath'
     ],
     ['getViewFile', 'Magento\Framework\View\FileSystem', 'Magento\Framework\View\Asset\File::getSourceFile()'],
+    ['updateOrderAction', 'Magento\Paypal\Controller\Express\AbstractExpress'],
+    ['updateOrder', 'Magento\Paypal\Model\Express\Checkout'],
+    ['_matchBnCountryCode', 'Magento\Paypal\Model\Config'],
     ['convertOldColumnDefinition', 'Magento\Framework\DB\Helper\AbstractHelper'],
     ['changeItemStatus', 'Magento\CatalogInventory\Model\Stock\Status'],
     ['getWebsiteDefaultStoreId', 'Magento\CatalogInventory\Model\Stock\Status'],
@@ -1728,4 +1754,6 @@ return array(
     ['getProductData', 'Magento\CatalogInventory\Model\Resource\Stock\Status'],
     ['getProduct', 'Magento\CatalogInventory\Model\Stock\Item'],
     ['reset', 'Magento\CatalogInventory\Model\Stock\Item'],
+    ['prepareValueForDuplicate', 'Magento\Catalog\Model\Product\Option\Value'],
+    ['prepareOptionForDuplicate', '\Magento\Catalog\Model\Product\Option'],
 );
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 202e86a8cb9..ea68041a59f 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
@@ -56,6 +56,7 @@ return array(
     array('_designProductSettingsApplied'),
     array('_directOutput', 'Magento\Framework\View\Layout'),
     array('_dirs', 'Magento\Framework\App\Resource'),
+    array('_entityInvalidatedIndexes', 'Magento\ImportExport\Model\Import'),
     array('_distroServerVars'),
     array('_entityIdsToIncrementIds'),
     array('entities', 'Magento\Framework\App\Resource'),
@@ -208,7 +209,6 @@ return array(
     array('_dirs', 'Magento\Core\Block\Template'),
     array('_applicationDirs', 'Magento\Framework\App\Config\FileResolver'),
     array('_dir', 'Magento\Core\Model\File\Storage'),
-    array('_dir', 'Magento\Framework\Locale\Hierarchy\Config\FileResolver'),
     array('_dirs', 'Magento\Core\Block\Template\Context'),
     array('_dir', 'Magento\Core\Model\Page\Asset\MergeService'),
     array('_dir', 'Magento\Core\Model\Page\Asset\MinifyService'),
@@ -226,7 +226,7 @@ return array(
     array('_dir', 'Magento\CatalogEvent\ModelEvent', '_filesystem'),
     array('_dir', 'Magento\Cms\Helper\Wyiswig\Images'),
     array('_dir', 'Magento\Email\Model\Template'),
-    array('_dir', 'Magento\ImportExport\Model\Import\Entity\Product', '_mediaDirectory'),
+    array('_dir', 'Magento\CatalogImportExport\Model\Import\Product', '_mediaDirectory'),
     array('_dir', 'Magento\ImportExport\Model\AbstractModel', '_varDirectory'),
     array('_coreDir', 'Magento\Install\Model\Installer\Console'),
     array('_dir', 'Magento\Install\Model\Installer\Filesystem'),
@@ -338,4 +338,5 @@ return array(
     ['_viewFileResolution', 'Magento\Framework\View\FileSystem', '_fileResolution, _localeFileResolution'],
     ['_inventoryModel', 'Magento\AdvancedCheckout\Model\Resource\Sku\Errors\Grid\Collection'],
     ['_productInstance', 'Magento\CatalogInventory\Model\Stock\Item'],
+    ['_regionBuilder', 'Magento\Customer\Model\Address\Converter'],
 );
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 ecbbe2237cd..c6f65868bbf 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
@@ -44,6 +44,8 @@ Magento/Catalog/Model/Layer
 Magento/Catalog/Model/Layer/Search.php
 Magento/Catalog/Model/Layer/Category.php
 Magento/Catalog/Service/V1/Data
+Magento/CatalogImportExport/Model/Export
+Magento/CatalogImportExport/Model/Import
 Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab
 Magento/Checkout/Block/Onepage
 Magento/Cms/Block/Adminhtml/Page/Edit
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcs/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcs/blacklist/common.txt
index 19a211773de..b547815cc68 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcs/blacklist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcs/blacklist/common.txt
@@ -2,23 +2,23 @@
 # Glob patterns are supported
 # Overrides the white list
 #
-# Formatter intorduces long line
+# Formatter introduces long line
 app/bootstrap.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/NewCategory.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Category.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Weight.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Catalog/Block/Adminhtml/Product/Options/Ajax.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Cms/Block/Adminhtml/Page/Edit/Tab/Design.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Backend/Block/Page/System/Config/Robots/Reset.php
-# Formatter intorduces long line
+# Formatter introduces long line
 app/code/Magento/Backend/Block/System/Store/Edit.php
 # Not magento code
 app/code/Zend
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
index b3840585683..e97a5303a15 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt
@@ -57,8 +57,10 @@ app/code/Magento/Customer/Controller
 app/code/Magento/Customer/Helper
 app/code/Magento/Customer/Model/Address/Config
 app/code/Magento/Customer/Model/Address/Config.php
-app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php
 app/code/Magento/Customer/Service
+app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php
+app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php
+app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php
 app/code/Magento/Directory/Model/Currency/DefaultLocator.php
 app/code/Magento/Directory/Model/Resource/Region
 app/code/Magento/Eav/Model/Cache/Type.php
@@ -75,8 +77,6 @@ app/code/Magento/ImportExport/Model/Export/ConfigInterface.php
 app/code/Magento/ImportExport/Model/Import/Config
 app/code/Magento/ImportExport/Model/Import/Config.php
 app/code/Magento/ImportExport/Model/Import/ConfigInterface.php
-app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php
-app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php
 app/code/Magento/ImportExport/Controller/Adminhtml/Import.php
 app/code/Magento/Index/Model/Indexer/Config
 app/code/Magento/Index/Model/Indexer/Config.php
@@ -118,6 +118,7 @@ app/code/Magento/Webapi
 app/code/Magento/GroupedProduct
 app/code/Magento/Wishlist/Block/Link.php
 dev/shell
+dev/tests/functional
 dev/tests/integration
 dev/tests/js
 dev/tests/performance
diff --git a/dev/tests/unit/testsuite/Magento/Backend/Helper/DataTest.php b/dev/tests/unit/testsuite/Magento/Backend/Helper/DataTest.php
index 0604112c484..f04c8baa28e 100644
--- a/dev/tests/unit/testsuite/Magento/Backend/Helper/DataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Backend/Helper/DataTest.php
@@ -68,4 +68,29 @@ class DataTest extends \PHPUnit_Framework_TestCase
 
         $this->assertEquals('custom_backend', $this->_helper->getAreaFrontName());
     }
+
+    /**
+     * @param array $inputString
+     * @param array $expected
+     *
+     * @dataProvider getPrepareFilterStringValuesDataProvider
+     */
+    public function testPrepareFilterStringValues(array $inputString, array $expected)
+    {
+        $inputString = base64_encode(http_build_query($inputString));
+
+        $actual = $this->_helper->prepareFilterString($inputString);
+
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function getPrepareFilterStringValuesDataProvider()
+    {
+        return array(
+            'both_spaces_value' => array(
+                array('field' => ' value '),
+                array('field' => 'value')
+            )
+        );
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php
index 8c8e61289a2..fa08eec1a86 100644
--- a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php
+++ b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php
@@ -128,6 +128,15 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase
         $this->priceMocks = [];
     }
 
+    public function testEmptySelectionPriceList()
+    {
+        $option = $this->getMock('Magento\Bundle\Model\Option', ['getSelections', '__wakeup'], [], '', false);
+        $option->expects($this->any())->method('getSelections')
+            ->will($this->returnValue(null));
+        $bundleProduct = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
+        $this->assertSame(array(), $this->model->createSelectionPriceList($option, $bundleProduct));
+    }
+
     /**
      * @dataProvider dataProviderForGetterAmount
      */
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Attribute/Backend/CustomlayoutupdateTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Attribute/Backend/CustomlayoutupdateTest.php
new file mode 100644
index 00000000000..de27b4f5b58
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Attribute/Backend/CustomlayoutupdateTest.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Attribute\Backend;
+
+use Magento\Framework\Object;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class CustomlayoutupdateTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var string
+     */
+    private $attributeName = 'private';
+
+    /**
+     * @var \Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate
+     */
+    private $model;
+
+    /**
+     * @expectedException \Magento\Eav\Model\Entity\Attribute\Exception
+     */
+    public function testValidateException()
+    {
+        $object = new Object();
+        $object->setData($this->attributeName, 'exception');
+        $this->model->validate($object);
+    }
+
+    /**
+     * @param string
+     * @dataProvider validateProvider
+     */
+    public function testValidate($data)
+    {
+        $object = new Object();
+        $object->setData($this->attributeName, $data);
+
+        $this->assertTrue($this->model->validate($object));
+        $this->assertTrue($this->model->validate($object));
+    }
+
+    /**
+     * @return array
+     */
+    public function validateProvider()
+    {
+        return [[''], ['xml']];
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Attribute\Backend\Customlayoutupdate',
+            [
+                'layoutUpdateValidatorFactory' => $this->getMockedLayoutUpdateValidatorFactory()
+            ]
+        );
+        $this->model->setAttribute($this->getMockedAttribute());
+    }
+
+    /**
+     * @return \Magento\Core\Model\Layout\Update\ValidatorFactory
+     */
+    private function getMockedLayoutUpdateValidatorFactory()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Core\Model\Layout\Update\ValidatorFactory');
+        $mockBuilder->disableOriginalConstructor();
+        $mockBuilder->setMethods(['create']);
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->getMockedValidator()));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Core\Model\Layout\Update\Validator
+     */
+    private function getMockedValidator()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Core\Model\Layout\Update\Validator');
+        $mockBuilder->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('isValid')
+            ->will(
+                /**
+                 * @param string $xml
+                 * $return bool
+                 */
+                $this->returnCallback(
+                    function ($xml) {
+                        if ($xml == 'exception') {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                )
+            );
+
+        $mock->expects($this->any())
+            ->method('getMessages')
+            ->will($this->returnValue(['error']));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+     */
+    private function getMockedAttribute()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute');
+        $mockBuilder->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getName')
+            ->will($this->returnValue($this->attributeName));
+
+        $mock->expects($this->any())
+            ->method('getIsRequired')
+            ->will($this->returnValue(false));
+
+        return $mock;
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Backend/SortbyTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Backend/SortbyTest.php
index 03219a91530..1b5aedf7bf6 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Backend/SortbyTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Backend/SortbyTest.php
@@ -37,54 +37,307 @@ class SortbyTest extends \PHPUnit_Framework_TestCase
      */
     protected $_objectHelper;
 
+    /**
+     * @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+     */
+    protected $_attribute;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface
+     */
+    protected $_scopeConfig;
+
     protected function setUp()
     {
         $this->_objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
+        $this->_scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
         $this->_model = $this->_objectHelper->getObject(
             'Magento\Catalog\Model\Category\Attribute\Backend\Sortby',
-            array('scopeConfig' => $scopeConfig)
+            array('scopeConfig' => $this->_scopeConfig)
         );
-        $attribute = $this->getMockForAbstractClass(
+        $this->_attribute = $this->getMockForAbstractClass(
             'Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
             array(),
             '',
             false,
             true,
             true,
-            array('getName', '__wakeup')
+            array('getName', '__call', 'isValueEmpty', 'getEntity', 'getFrontend', '__wakeup')
         );
-        $attribute->expects($this->any())->method('getName')->will($this->returnValue(self::DEFAULT_ATTRIBUTE_CODE));
-        $this->_model->setAttribute($attribute);
-    }
-
-    protected function tearDown()
-    {
-        $this->_model = null;
+        $this->_model->setAttribute($this->_attribute);
     }
 
     /**
+     * @param $attributeCode
      * @param $data
      * @param $expected
      * @dataProvider beforeSaveDataProvider
      */
-    public function testBeforeSave($data, $expected)
+    public function testBeforeSave($attributeCode, $data, $expected)
     {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue($attributeCode));
         $object = new \Magento\Framework\Object($data);
         $this->_model->beforeSave($object);
-        $this->assertTrue($object->hasData(self::DEFAULT_ATTRIBUTE_CODE));
-        $this->assertSame($expected, $object->getData(self::DEFAULT_ATTRIBUTE_CODE));
+        $this->assertTrue($object->hasData($attributeCode));
+        $this->assertSame($expected, $object->getData($attributeCode));
     }
 
     public function beforeSaveDataProvider()
     {
         return array(
             'attribute with specified value' => array(
-                array(self::DEFAULT_ATTRIBUTE_CODE => 'test_value'),
+                self::DEFAULT_ATTRIBUTE_CODE,
+                [self::DEFAULT_ATTRIBUTE_CODE => 'test_value'],
                 'test_value'
             ),
-            'attribute with default value' => array(array(self::DEFAULT_ATTRIBUTE_CODE => null), null),
-            'attribute does not exist' => array(array(), false)
+            'attribute with default value' => array(
+                self::DEFAULT_ATTRIBUTE_CODE,
+                [self::DEFAULT_ATTRIBUTE_CODE => null],
+                null
+            ),
+            'attribute does not exist' => array(
+                self::DEFAULT_ATTRIBUTE_CODE,
+                array(),
+                false
+            ),
+            'attribute sort by empty' => array(
+                'available_sort_by',
+                ['available_sort_by' => null],
+                ''
+            ),
+            'attribute sort by' => array(
+                'available_sort_by',
+                ['available_sort_by' => ['test', 'value']],
+                'test,value'
+            )
+        );
+    }
+
+    /**
+     * @param $attributeCode
+     * @param $data
+     * @param $expected
+     * @dataProvider afterLoadDataProvider
+     */
+    public function testAfterLoad($attributeCode, $data, $expected)
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue($attributeCode));
+        $object = new \Magento\Framework\Object($data);
+        $this->_model->afterLoad($object);
+        $this->assertTrue($object->hasData($attributeCode));
+        $this->assertSame($expected, $object->getData($attributeCode));
+    }
+
+    public function afterLoadDataProvider()
+    {
+        return array(
+            'attribute with specified value' => array(
+                self::DEFAULT_ATTRIBUTE_CODE,
+                [self::DEFAULT_ATTRIBUTE_CODE => 'test_value'],
+                'test_value'
+            ),
+            'attribute sort by empty' => array(
+                'available_sort_by',
+                ['available_sort_by' => null],
+                null
+            ),
+            'attribute sort by' => array(
+                'available_sort_by',
+                ['available_sort_by' => 'test,value'],
+                ['test', 'value']
+            )
+        );
+    }
+
+    /**
+     * @param $attributeData
+     * @param $data
+     * @param $expected
+     * @dataProvider validateDataProvider
+     */
+    public function testValidate($attributeData, $data, $expected)
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue($attributeData['code']));
+        $this->_attribute
+            ->expects($this->at(1))
+            ->method('__call')
+            ->with('getIsRequired')
+            ->will($this->returnValue($attributeData['isRequired']));
+        $this->_attribute
+            ->expects($this->any())
+            ->method('isValueEmpty')
+            ->will($this->returnValue($attributeData['isValueEmpty']));
+        $object = new \Magento\Framework\Object($data);
+        $this->assertSame($expected, $this->_model->validate($object));
+    }
+
+    public function validateDataProvider()
+    {
+        return array(
+            'is not required' => array(
+                ['code' => self::DEFAULT_ATTRIBUTE_CODE, 'isRequired' => false, 'isValueEmpty' => false],
+                array(),
+                true
+            ),
+            'required, empty, not use config case 1' => array(
+                ['code' => self::DEFAULT_ATTRIBUTE_CODE, 'isRequired' => true, 'isValueEmpty' => true],
+                [self::DEFAULT_ATTRIBUTE_CODE => array(), 'use_post_data_config' => []],
+                false
+            ),
+            'required, empty, not use config case 2' => array(
+                ['code' => self::DEFAULT_ATTRIBUTE_CODE, 'isRequired' => true, 'isValueEmpty' => true],
+                [self::DEFAULT_ATTRIBUTE_CODE => array(), 'use_post_data_config' => ['config']],
+                false
+            ),
+            'required, empty, use config' => array(
+                ['code' => self::DEFAULT_ATTRIBUTE_CODE, 'isRequired' => true, 'isValueEmpty' => true],
+                [self::DEFAULT_ATTRIBUTE_CODE => array(), 'use_post_data_config' => [self::DEFAULT_ATTRIBUTE_CODE]],
+                true
+            ),
+        );
+    }
+
+    public function testValidateUnique()
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue('attribute_name'));
+        $this->_attribute->expects($this->at(1))->method('__call')->with('getIsRequired');
+        $this->_attribute->expects($this->at(2))->method('__call')->with('getIsUnique')->will($this->returnValue(true));
+
+        $entityMock = $this->getMockForAbstractClass(
+            'Magento\Eav\Model\Entity\AbstractEntity',
+            array(),
+            '',
+            false,
+            true,
+            true,
+            array('checkAttributeUniqueValue')
+        );
+        $this->_attribute->expects($this->any())->method('getEntity')->will($this->returnValue($entityMock));
+        $entityMock->expects($this->at(0))->method('checkAttributeUniqueValue')->will($this->returnValue(true));
+        $this->assertTrue($this->_model->validate(new \Magento\Framework\Object()));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testValidateUniqueException()
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue('attribute_name'));
+        $this->_attribute->expects($this->at(1))->method('__call')->with('getIsRequired');
+        $this->_attribute->expects($this->at(2))->method('__call')->with('getIsUnique')->will($this->returnValue(true));
+
+        $entityMock = $this->getMockForAbstractClass(
+            'Magento\Eav\Model\Entity\AbstractEntity',
+            array(),
+            '',
+            false,
+            true,
+            true,
+            array('checkAttributeUniqueValue')
+        );
+        $frontMock = $this->getMockForAbstractClass(
+            'Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend',
+            array(),
+            '',
+            false,
+            true,
+            true,
+            array('getLabel')
+        );
+        $this->_attribute->expects($this->any())->method('getEntity')->will($this->returnValue($entityMock));
+        $this->_attribute->expects($this->any())->method('getFrontend')->will($this->returnValue($frontMock));
+        $entityMock->expects($this->at(0))->method('checkAttributeUniqueValue')->will($this->returnValue(false));
+        $this->assertTrue($this->_model->validate(new \Magento\Framework\Object()));
+    }
+
+    /**
+     * @param $attributeCode
+     * @param $data
+     * @dataProvider validateDefaultSortDataProvider
+     */
+    public function testValidateDefaultSort($attributeCode, $data)
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue($attributeCode));
+        $this->_scopeConfig->expects($this->any())->method('getValue')->will($this->returnValue('value2'));
+        $object = new \Magento\Framework\Object($data);
+        $this->assertTrue($this->_model->validate($object));
+    }
+
+    public function validateDefaultSortDataProvider()
+    {
+        return array(
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => ['value1', 'value2'],
+                    'default_sort_by' => 'value2',
+                    'use_post_data_config' => array()
+                ]
+            ),
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => 'value1,value2',
+                    'use_post_data_config' => ['default_sort_by']
+                ]
+            ),
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => NULL,
+                    'default_sort_by' => NULL,
+                    'use_post_data_config' => ['available_sort_by', 'default_sort_by', 'filter_price_range']
+                ]
+            ),
+        );
+    }
+
+    /**
+     * @param $attributeCode
+     * @param $data
+     * @dataProvider validateDefaultSortException
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testValidateDefaultSortException($attributeCode, $data)
+    {
+        $this->_attribute->expects($this->any())->method('getName')->will($this->returnValue($attributeCode));
+        $this->_scopeConfig->expects($this->any())->method('getValue')->will($this->returnValue('another value'));
+        $object = new \Magento\Framework\Object($data);
+        $this->_model->validate($object);
+    }
+
+    public function validateDefaultSortException()
+    {
+        return array(
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => NULL,
+                    'use_post_data_config' => ['default_sort_by']
+                ]
+            ),
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => NULL,
+                    'use_post_data_config' => []
+                ]
+            ),
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => ['value1', 'value2'],
+                    'default_sort_by' => 'another value',
+                    'use_post_data_config' => array()
+                ]
+            ),
+            array(
+                'default_sort_by',
+                [
+                    'available_sort_by' => 'value1',
+                    'use_post_data_config' => array()
+                ]
+            ),
         );
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/LayoutTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/LayoutTest.php
new file mode 100644
index 00000000000..ff0936ba8e6
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/LayoutTest.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Category\Attribute\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class LayoutTest extends \PHPUnit_Framework_TestCase
+{
+    private $testArray = ['test1', ['test1']];
+    /**
+     * @var \Magento\Catalog\Model\Category\Attribute\Source\Layout
+     */
+    private $model;
+
+    public function testGetAllOptions()
+    {
+        $assertArray = $this->testArray;
+        array_unshift($assertArray, ['value' => '', 'label' => __('No layout updates')]);
+        $this->assertEquals($assertArray, $this->model->getAllOptions());
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Category\Attribute\Source\Layout',
+            [
+                'pageSourceLayout' => $this->getMockedLayout()
+            ]
+        );
+    }
+
+    /**
+     * @return \Magento\Theme\Model\Layout\Source\Layout
+     */
+    private function getMockedLayout()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Theme\Model\Layout\Source\Layout');
+        $mockBuilder->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('toOptionArray')
+            ->will($this->returnValue($this->testArray));
+
+        return $mock;
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/PageTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/PageTest.php
new file mode 100644
index 00000000000..0b7b10ca352
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/PageTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Category\Attribute\Source;
+
+use Magento\Cms\Model\Resource\Block\CollectionFactory;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class PageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var array
+     */
+    private $testArray = ['test1', ['test1']];
+
+    /**
+     * @var \Magento\Catalog\Model\Category\Attribute\Source\Page
+     */
+    private $model;
+
+    public function testGetAllOptions()
+    {
+        $assertArray = $this->testArray;
+        array_unshift($assertArray, ['value' => '', 'label' => __('Please select a static block.')]);
+        $this->assertEquals($assertArray, $this->model->getAllOptions());
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Category\Attribute\Source\Page',
+            [
+                'blockCollectionFactory' => $this->getMockedBlockCollectionFactory()
+            ]
+        );
+    }
+
+    /**
+     * @return \Magento\Cms\Model\Resource\Block\CollectionFactory
+     */
+    private function getMockedBlockCollectionFactory()
+    {
+        $mockedCollection = $this->getMockedCollection();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Cms\Model\Resource\Block\CollectionFactory');
+        $mock = $mockBuilder->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($mockedCollection));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Framework\Data\Collection
+     */
+    private function getMockedCollection()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Data\Collection');
+        $mock = $mockBuilder->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->expects($this->any())
+            ->method('load')
+            ->will($this->returnValue($mock));
+
+        $mock->expects($this->any())
+            ->method('toOptionArray')
+            ->will($this->returnValue($this->testArray));
+
+        return $mock;
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/SortbyTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/SortbyTest.php
new file mode 100644
index 00000000000..73a0c14f2d1
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Category/Attribute/Source/SortbyTest.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Category\Attribute\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class SortbyTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Category\Attribute\Source\Sortby
+     */
+    private $model;
+
+    public function testGetAllOptions()
+    {
+        $validResult = [['label' => __('Position'), 'value' => 'position'], ['label' => __('fl'), 'value' => 'fc']];
+        $this->assertEquals($validResult, $this->model->getAllOptions());
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Category\Attribute\Source\Sortby',
+            [
+                'catalogConfig' => $this->getMockedConfig()
+            ]
+        );
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Config
+     */
+    private function getMockedConfig()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Config');
+        $mockBuilder->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getAttributesUsedForSortBy')
+            ->will($this->returnValue([['frontend_label' => 'fl', 'attribute_code' => 'fc']]));
+
+        return $mock;
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/CatalogClone/Media/ImageTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/CatalogClone/Media/ImageTest.php
new file mode 100644
index 00000000000..b012e76cb88
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/CatalogClone/Media/ImageTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\CatalogClone\Media;
+
+use Magento\Catalog\Model\Product;
+use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ImageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\CatalogClone\Media\Image
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $eavConfig;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attributeCollectionFactory;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Product\Attribute\Collection|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attributeCollection;
+
+    /**
+     * @var \Magento\Eav\Model\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attribute;
+
+    protected function setUp()
+    {
+        $this->eavConfig = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeCollection = $this->getMockBuilder(
+            '\Magento\Catalog\Model\Resource\Product\Attribute\Collection'
+        )
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->attributeCollectionFactory = $this->getMockBuilder(
+            'Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory'
+        )
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->attributeCollectionFactory->expects($this->any())->method('create')->will(
+            $this->returnValue($this->attributeCollection)
+        );
+
+        $this->attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Config\CatalogClone\Media\Image',
+            [
+                'eavConfig' => $this->eavConfig,
+                'attributeCollectionFactory' => $this->attributeCollectionFactory
+            ]
+        );
+    }
+
+    public function testGetPrefixes()
+    {
+        $entityTypeId = 3;
+        /** @var \Magento\Eav\Model\Entity\Type|\PHPUnit_Framework_MockObject_MockObject $entityType */
+        $entityType = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $entityType->expects($this->once())->method('getId')->will($this->returnValue($entityTypeId));
+
+        /** @var AbstractFrontend|\PHPUnit_Framework_MockObject_MockObject $frontend */
+        $frontend = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend')
+            ->setMethods(['getLabel'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $frontend->expects($this->once())->method('getLabel')->will($this->returnValue('testLabel'));
+
+        $this->attributeCollection->expects($this->once())->method('setEntityTypeFilter')->with(
+            $this->equalTo($entityTypeId)
+        );
+        $this->attributeCollection->expects($this->once())->method('setFrontendInputTypeFilter')->with(
+            $this->equalTo('media_image')
+        );
+
+        $this->attribute->expects($this->once())->method('getAttributeCode')->will(
+            $this->returnValue('attributeCode')
+        );
+        $this->attribute->expects($this->once())->method('getFrontend')->will(
+            $this->returnValue($frontend)
+        );
+
+        $this->attributeCollection->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$this->attribute]))
+        );
+
+        $this->eavConfig->expects($this->any())->method('getEntityType')->with(
+            $this->equalTo(Product::ENTITY)
+        )->will($this->returnValue($entityType));
+
+        $this->assertEquals([['field' => 'attributeCode_', 'label' => 'testLabel']], $this->model->getPrefixes());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/CategoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/CategoryTest.php
new file mode 100644
index 00000000000..2c07175562a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/CategoryTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
+
+class CategoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\Source\Category
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Category\Collection|MockObject
+     */
+    private $categoryCollection;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Category|MockObject
+     */
+    private $category;
+
+    protected function setUp()
+    {
+        $this->categoryCollection = $this->getMockBuilder('Magento\Catalog\Model\Resource\Category\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->category = $this->getMockBuilder('Magento\Catalog\Model\Resource\Category')
+            ->setMethods(['getName', 'getId'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        /** @var \Magento\Catalog\Model\Resource\Category\CollectionFactory|MockObject $categoryCollectionFactory */
+        $categoryCollectionFactory = $this->getMockBuilder('Magento\Catalog\Model\Resource\Category\CollectionFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $categoryCollectionFactory->expects($this->any())->method('create')->will(
+            $this->returnValue($this->categoryCollection)
+        );
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject('Magento\Catalog\Model\Config\Source\Category', [
+                'categoryCollectionFactory' => $categoryCollectionFactory
+            ]);
+    }
+
+    public function testToOptionArray()
+    {
+        $expect = [
+            ['label' => __('-- Please Select a Category --'), 'value' => ''],
+            ['label' => 'name', 'value' => 3]
+        ];
+
+        $this->categoryCollection->expects($this->once())->method('addAttributeToSelect')->with(
+            $this->equalTo('name')
+        )->will($this->returnValue($this->categoryCollection));
+        $this->categoryCollection->expects($this->once())->method('addRootLevelFilter')->will(
+            $this->returnValue($this->categoryCollection)
+        );
+        $this->categoryCollection->expects($this->once())->method('load');
+        $this->categoryCollection->expects($this->any())->method('getIterator')->will(
+            $this->returnValue(new \ArrayIterator([$this->category]))
+        );
+
+        $this->category->expects($this->once())->method('getName')->will($this->returnValue('name'));
+        $this->category->expects($this->once())->method('getId')->will($this->returnValue(3));
+
+        $this->assertEquals($expect, $this->model->toOptionArray());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/GridPerPageTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/GridPerPageTest.php
new file mode 100644
index 00000000000..26fd1d9d874
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/GridPerPageTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class GridPerPageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\Source\GridPerPage
+     */
+    private $model;
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Config\Source\GridPerPage',
+            ['perPageValues' => 'some,values']
+        );
+    }
+
+    public function testToOptionalArray()
+    {
+        $expect = [
+            ['value' => 'some', 'label' => 'some'],
+            ['value' => 'values', 'label' => 'values'],
+        ];
+
+        $this->assertEquals($expect, $this->model->toOptionArray());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListPerPageTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListPerPageTest.php
new file mode 100644
index 00000000000..15afb19b9e0
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListPerPageTest.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ListPerPageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\Source\ListPerPage
+     */
+    private $model;
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Config\Source\ListPerPage',
+            ['options' => 'some,test,options']
+        );
+    }
+
+    public function testToOptionArray()
+    {
+        $expect = [
+            ['value' => 'some', 'label' => 'some'],
+            ['value' => 'test', 'label' => 'test'],
+            ['value' => 'options', 'label' => 'options'],
+        ];
+
+        $this->assertEquals($expect, $this->model->toOptionArray());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListSortTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListSortTest.php
new file mode 100644
index 00000000000..6dbbd956185
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/ListSortTest.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\Source;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ListSortTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\Source\ListSort
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\Config|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $catalogConfig;
+
+    protected function setUp()
+    {
+        $this->catalogConfig = $this->getMockBuilder('Magento\Catalog\Model\Config')->
+            disableOriginalConstructor()->
+            getMock();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Config\Source\ListSort',
+            ['catalogConfig' => $this->catalogConfig]
+        );
+    }
+
+    public function testToOptionalArray()
+    {
+        $except = [
+            ['label' => __('Position'), 'value' => 'position'],
+            ['label' => 'testLabel', 'value' => 'testAttributeCode']
+        ];
+        $this->catalogConfig->expects($this->any())->method('getAttributesUsedForSortBy')
+            ->will($this->returnValue([['frontend_label' => 'testLabel', 'attribute_code' => 'testAttributeCode']]));
+
+        $this->assertEquals($except, $this->model->toOptionArray());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/Product/Options/TypeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/Product/Options/TypeTest.php
new file mode 100644
index 00000000000..ba8ab37cfac
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Config/Source/Product/Options/TypeTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Config\Source\Product\Options;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class TypeTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Config\Source\Product\Options\Type
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\ProductOptions\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productOptionConfig;
+
+    protected function setUp()
+    {
+        $this->productOptionConfig = $this->getMockBuilder('Magento\Catalog\Model\ProductOptions\ConfigInterface')
+            ->setMethods(['getAll'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Config\Source\Product\Options\Type',
+            ['productOptionConfig' => $this->productOptionConfig]
+        );
+    }
+
+    public function testToOptionArray()
+    {
+        $allOptions = [
+            [
+                'types' => [
+                    ['disabled' => false, 'label' => 'typeLabel', 'name' => 'typeName']
+                ],
+                'label' => 'optionLabel'
+            ],
+            [
+                'types' => [
+                    ['disabled' => true]
+                ],
+                'label' => 'optionLabelDisabled'
+            ]
+        ];
+        $expect = [
+            ['value' => '', 'label' => __('-- Please select --')],
+            ['label' => 'optionLabel', 'value' => [['label' => 'typeLabel', 'value' => 'typeName']]]
+        ];
+
+        $this->productOptionConfig->expects($this->any())->method('getAll')->will($this->returnValue($allOptions));
+
+        $this->assertEquals($expect, $this->model->toOptionArray());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/FactoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/FactoryTest.php
new file mode 100644
index 00000000000..b7811b50fb5
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/FactoryTest.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model;
+
+class FactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Option
+     */
+    protected $model;
+
+    /**
+     * @var Factory
+     */
+    protected $factory;
+
+    public function testCreate()
+    {
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option', $this->factory->create('model', []));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testExceptionCreate()
+    {
+        $this->factory->create('null', []);
+    }
+
+    protected function setUp()
+    {
+        $this->model = $this->getMock('Magento\Catalog\Model\Product\Option', [], [], '', false);
+
+        $this->setObjectManager();
+
+        $this->factory = new Factory($this->objectManager);
+    }
+
+    protected function setObjectManager()
+    {
+        $this->objectManager = $this->getMock('\Magento\Framework\ObjectManager', [], [], '', false);
+
+        $this->objectManager
+            ->expects($this->any())
+            ->method('create')
+            ->with($this->logicalOr($this->equalTo('model'), $this->equalTo('null')), $this->equalTo([]))
+            ->will($this->returnCallback(function ($className) {
+                $returnValue = null;
+                if ($className == 'model') {
+                    $returnValue = $this->model;
+                }
+                return $returnValue;
+            }));
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/FlatTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/FlatTest.php
new file mode 100644
index 00000000000..af88ad65d89
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/FlatTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Indexer\Product;
+
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class FlatTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Product\Flat
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productFlatIndexerRow;
+
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Rows|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productFlatIndexerRows;
+
+    /**
+     * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Full|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productFlatIndexerFull;
+
+    protected function setUp()
+    {
+        $this->productFlatIndexerRow = $this->getMockBuilder('Magento\Catalog\Model\Indexer\Product\Flat\Action\Row')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->productFlatIndexerRows = $this->getMockBuilder('Magento\Catalog\Model\Indexer\Product\Flat\Action\Rows')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->productFlatIndexerFull = $this->getMockBuilder('Magento\Catalog\Model\Indexer\Product\Flat\Action\Full')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            'Magento\Catalog\Model\Indexer\Product\Flat',
+            [
+                'productFlatIndexerRow' => $this->productFlatIndexerRow,
+                'productFlatIndexerRows' => $this->productFlatIndexerRows,
+                'productFlatIndexerFull' => $this->productFlatIndexerFull
+            ]
+        );
+    }
+
+    public function testExecuteAndExecuteList()
+    {
+        $except = ['test'];
+        $this->productFlatIndexerRows->expects($this->any())->method('execute')->with($this->equalTo($except));
+
+        $this->model->execute($except);
+        $this->model->executeList($except);
+    }
+
+    public function testExecuteFull()
+    {
+        $this->productFlatIndexerFull->expects($this->any())->method('execute');
+
+        $this->model->executeFull();
+    }
+
+    public function testExecuteRow()
+    {
+        $except = 5;
+        $this->productFlatIndexerRow->expects($this->any())->method('execute')->with($this->equalTo($except));
+
+        $this->model->executeRow($except);
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/Filter/DecimalTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/Filter/DecimalTest.php
new file mode 100644
index 00000000000..f6d58c651f1
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/Filter/DecimalTest.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Layer\Filter;
+
+class DecimalTest extends \PHPUnit_Framework_TestCase
+{
+    public function testConstructorRequestVarIsOverwrittenCorrectlyInParent()
+    {
+        $attributeModel = $this->getMock(
+            'Magento\Catalog\Model\Resource\Eav\Attribute',
+            array('getAttributeCode', '__wakeup'),
+            array(),
+            '',
+            false
+        );
+        $attributeModel->expects($this->once())->method('getAttributeCode')->will($this->returnValue('price1'));
+
+        $filterDecimalFactory = $this->getMock(
+            'Magento\Catalog\Model\Resource\Layer\Filter\DecimalFactory',
+            array('create')
+        );
+        $filterDecimalFactory->expects($this->once())->method('create')->will(
+            $this->returnValue(
+                $this->getMock('Magento\Catalog\Model\Resource\Layer\Filter\Decimal', array(), array(), '', false)
+            )
+        );
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $instance = $objectManager->getObject(
+            'Magento\Catalog\Model\Layer\Filter\Decimal',
+            array(
+                'filterDecimalFactory' => $filterDecimalFactory,
+                'data' => array('attribute_model' => $attributeModel)
+            )
+        );
+        $this->assertSame('price1', $instance->getRequestVar());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/StateTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/StateTest.php
new file mode 100644
index 00000000000..2c5088c8af4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layer/StateTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Layer;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class StateTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Layer\State
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\Layer\Filter\Item|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $item;
+
+    protected function setUp()
+    {
+        $this->item = $this->getMockBuilder('Magento\Catalog\Model\Layer\Filter\Item')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject('Magento\Catalog\Model\Layer\State');
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testSetFiltersException()
+    {
+        $this->model->setFilters($this->item);
+    }
+
+    public function testSetFilters()
+    {
+        $expect = [$this->item];
+
+        $this->model->setFilters($expect);
+        $this->assertEquals($expect, $this->model->getFilters());
+    }
+
+    public function testAddFilter()
+    {
+        $expect = [$this->item];
+
+        $this->model->addFilter($this->item);
+
+        $this->assertEquals($expect, $this->model->getFilters());
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/UrlkeyTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/UrlkeyTest.php
new file mode 100644
index 00000000000..fb24ac7b9bb
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/UrlkeyTest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Attribute\Backend;
+
+use Magento\Framework\Object;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class UrlkeyTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Attribute\Backend\Urlkey
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attribute;
+
+    protected function setUp()
+    {
+
+        $this->attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->setMethods(['__wakeup', 'getName'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject('Magento\Catalog\Model\Product\Attribute\Backend\Urlkey');
+        $this->model->setAttribute($this->attribute);
+    }
+
+    /**
+     * @param bool|string $objData
+     * @dataProvider beforeSaveProvider
+     */
+    public function testBeforeSave($objData)
+    {
+        $attributeName = 'attr';
+        $this->attribute->expects($this->once())->method('getName')->will($this->returnValue($attributeName));
+
+        /** @var \Magento\Catalog\Model\Product\Url|\PHPUnit_Framework_MockObject_MockObject $object */
+        $object = $this->getMockBuilder('Magento\Catalog\Model\Product\Url')
+            ->setMethods(['getName', 'getData', 'setData', 'formatUrlKey'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $object->expects($this->once())->method('getData')->with($this->equalTo($attributeName))->will(
+            $this->returnValue($objData)
+        );
+        $object->expects($this->any())->method('getName')->will($this->returnValue('testData'));
+        $object->expects($this->any())->method('setData')->with(
+            $this->equalTo($attributeName),
+            $this->logicalOr($this->equalTo('testData'), $this->equalTo('someData'))
+        );
+        $object->expects($this->any())->method('formatUrlKey')->with(
+            $this->logicalOr($this->equalTo('testData'), $this->equalTo('someData'))
+        )->will(
+                $this->returnCallback(
+                    function ($data) {
+                        return $data;
+                    }
+                )
+            );
+
+        $this->model->beforeSave($object);
+    }
+
+    public function beforeSaveProvider()
+    {
+        return [[false], [''], ['someData']];
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Frontend/ImageTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Frontend/ImageTest.php
new file mode 100644
index 00000000000..5def7e22bc2
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/Frontend/ImageTest.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Attribute\Frontend;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ImageTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Attribute\Frontend\Image
+     */
+    private $model;
+
+    public function testGetUrl()
+    {
+        $this->assertEquals('catalog/product/image.jpg', $this->model->getUrl($this->getMockedProduct()));
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Product\Attribute\Frontend\Image',
+            ['storeManager' => $this->getMockedStoreManager()]
+        );
+        $this->model->setAttribute($this->getMockedAttribute());
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product
+     */
+    private function getMockedProduct()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product');
+        $mock = $mockBuilder->setMethods(['getData', 'getStore', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->expects($this->any())
+            ->method('getData')
+            ->will($this->returnValue('image.jpg'));
+
+        $mock->expects($this->any())
+            ->method('getStore');
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Store\Model\StoreManagerInterface
+     */
+    private function getMockedStoreManager()
+    {
+        $mockedStore = $this->getMockedStore();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Store\Model\StoreManagerInterface');
+        $mock = $mockBuilder->setMethods(['getStore'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($mockedStore));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Store\Model\Store
+     */
+    private function getMockedStore()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Store\Model\Store');
+        $mock = $mockBuilder->setMethods(['getBaseUrl', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('getBaseUrl')
+            ->will($this->returnValue(''));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
+     */
+    private function getMockedAttribute()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute');
+        $mockBuilder->setMethods(['getAttributeCode', '__wakeup']);
+        $mockBuilder->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('getAttributeCode');
+
+        return $mock;
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/GroupTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/GroupTest.php
new file mode 100644
index 00000000000..e9a3efa9524
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Attribute/GroupTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Attribute;
+
+use Magento\Framework\Object;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class GroupTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Attribute\Group
+     */
+    private $model;
+
+    public function testHasSystemAttributes()
+    {
+        $this->model->setId(1);
+        $this->assertTrue($this->model->hasSystemAttributes());
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Product\Attribute\Group',
+            [
+                'attributeCollectionFactory' => $this->getMockedCollectionFactory()
+            ]
+        );
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory
+     */
+    private function getMockedCollectionFactory()
+    {
+        $mockedCollection = $this->getMockedCollection();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory');
+        $mock = $mockBuilder->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($mockedCollection));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Resource\Product\Attribute\Collection
+     */
+    private function getMockedCollection()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Attribute\Collection');
+        $mock = $mockBuilder->disableOriginalConstructor()
+            ->getMock();
+
+        $item = new Object();
+        $item->setIsUserDefine(false);
+
+        $mock->expects($this->any())
+            ->method('setAttributeGroupFilter')
+            ->will($this->returnValue($mock));
+        $mock->expects($this->any())
+            ->method('getIterator')
+            ->will($this->returnValue(new \ArrayIterator([$item])));
+
+        return $mock;
+    }
+}
+ 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
new file mode 100644
index 00000000000..ccaeefe9d8a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/ConditionTest.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product;
+
+use Magento\Eav\Model\Entity\Collection\AbstractCollection;
+use Magento\TestFramework\Helper\ObjectManager;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Framework\DB\Select;
+
+class ConditionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Condition
+     */
+    private $model;
+
+    public function testApplyToCollection()
+    {
+        $collection = $this->getMockedAbstractCollection();
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Product\Condition',
+            $this->model->applyToCollection($collection)
+        );
+    }
+
+    public function testGetIdsSelect()
+    {
+        $adapter = $this->getMockedAdapterInterface();
+        $this->assertInstanceOf('\Magento\Framework\DB\Select', $this->model->getIdsSelect($adapter));
+        $this->model->setTable(null);
+        $this->assertEmpty($this->model->getIdsSelect($adapter));
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject('\Magento\Catalog\Model\Product\Condition');
+        $this->model->setTable('testTable')
+            ->setPkFieldName('testFieldName');
+    }
+
+    /**
+     * @return AbstractCollection
+     */
+    private function getMockedAbstractCollection()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Eav\Model\Entity\Collection\AbstractCollection')
+            ->setMethods(['joinTable'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('joinTable');
+
+        return $mock;
+    }
+
+    /**
+     * @return AdapterInterface
+     */
+    private function getMockedAdapterInterface()
+    {
+        $mockedDbSelect = $this->getMockedDbSelect();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\DB\Adapter\AdapterInterface')
+            ->setMethods(['select'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('select')
+            ->will($this->returnValue($mockedDbSelect));
+
+        return $mock;
+    }
+
+    /**
+     * @return Select
+     */
+    private function getMockedDbSelect()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\DB\Select')
+            ->setMethods(['from'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('from')
+            ->will($this->returnValue($mock));
+
+        return $mock;
+    }
+} 
\ No newline at end of file
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
new file mode 100644
index 00000000000..d1763dffe64
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Initialization/Helper/ProductLinksTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Initialization\Helper;
+
+use Magento\Catalog\Model\Product;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ProductLinksTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks
+     */
+    private $model;
+
+    public function testInitializeLinks()
+    {
+        $links = ['related' => ['data'], 'upsell' => ['data'], 'crosssell' => ['data']];
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Product',
+            $this->model->initializeLinks($this->getMockedProduct(), $links)
+        );
+
+    }
+
+    protected function setUp()
+    {
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject('\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks');
+    }
+
+    /**
+     * @return Product
+     */
+    private function getMockedProduct()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(
+                [
+                    'getRelatedReadonly',
+                    'getUpsellReadonly',
+                    'getCrosssellReadonly',
+                    'setCrossSellLinkData',
+                    'setUpSellLinkData',
+                    'setRelatedLinkData',
+                    '__wakeup'
+                ]
+            )
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getRelatedReadonly')
+            ->will($this->returnValue(false));
+
+        $mock->expects($this->any())
+            ->method('getUpsellReadonly')
+            ->will($this->returnValue(false));
+
+        $mock->expects($this->any())
+            ->method('getCrosssellReadonly')
+            ->will($this->returnValue(false));
+
+        $mock->expects($this->any())
+            ->method('setCrossSellLinkData');
+
+        $mock->expects($this->any())
+            ->method('setUpSellLinkData');
+
+        $mock->expects($this->any())
+            ->method('setRelatedLinkData');
+
+        return $mock;
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/UrlBuilderTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/UrlBuilderTest.php
new file mode 100644
index 00000000000..9b4c5e0b01a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/UrlBuilderTest.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Option;
+
+use Magento\TestFramework\Helper\ObjectManager;
+
+class UrlBuilderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Option\UrlBuilder
+     */
+    private $model;
+
+    public function testGetUrl()
+    {
+        $this->assertEquals('testResult', $this->model->getUrl('router', []));
+    }
+
+    protected function setUp()
+    {
+        $mockedFrontendUrlBuilder = $this->getMockedFrontendUrlBuilder();
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Product\Option\UrlBuilder',
+            ['frontendUrlBuilder' => $mockedFrontendUrlBuilder]
+        );
+    }
+
+    /**
+     * @return \Magento\Framework\UrlInterface
+     */
+    private function getMockedFrontendUrlBuilder()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\UrlInterface')
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('getUrl')
+            ->will($this->returnValue('testResult'));
+
+        return $mock;
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/ValueTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/ValueTest.php
new file mode 100644
index 00000000000..470a8e5de70
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Option/ValueTest.php
@@ -0,0 +1,304 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Model\Product\Option;
+
+use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\Product\Option;
+use Magento\Framework\Model\ActionValidator\RemoveAction;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class ValueTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Model\Product\Option\Value
+     */
+    private $model;
+
+    public function testSaveProduct()
+    {
+        $this->model->setValues([100])
+            ->setData('option_type_id', -1)
+            ->setDataChanges(false)
+            ->isDeleted(false);
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option\Value', $this->model->saveValues());
+
+        $this->model->setData('is_delete', 1)
+            ->setData('option_type_id', 1)
+            ->setValues([100]);
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option\Value', $this->model->saveValues());
+    }
+
+    public function testGetPrice()
+    {
+        $this->model->setPrice(1000);
+        $this->model->setPriceType(Value::TYPE_PERCENT);
+        $this->assertEquals(1000, $this->model->getPrice(false));
+
+        $this->assertEquals(100, $this->model->getPrice(true));
+    }
+
+    public function testGetValuesCollection()
+    {
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Resource\Product\Option\Value\Collection',
+            $this->model->getValuesCollection($this->getMockedOption())
+        );
+    }
+
+    public function testGetValuesByOption()
+    {
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Resource\Product\Option\Value\Collection',
+            $this->model->getValuesByOption([1], 1, 1)
+        );
+    }
+
+    public function testGetProduct()
+    {
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product', $this->model->getProduct());
+    }
+
+    public function testDuplicate()
+    {
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option\Value', $this->model->duplicate(1, 1));
+    }
+
+    public function testDeleteValues()
+    {
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option\Value', $this->model->deleteValues(1));
+    }
+
+    public function testDeleteValue()
+    {
+        $this->assertInstanceOf('\Magento\Catalog\Model\Product\Option\Value', $this->model->deleteValue(1));
+    }
+
+    protected function setUp()
+    {
+        $mockedResource = $this->getMockedResource();
+        $mockedCollectionFactory = $this->getMockedValueCollectionFactory();
+        $mockedContext = $this->getMockedContext();
+        $helper = new ObjectManager($this);
+        $this->model = $helper->getObject(
+            '\Magento\Catalog\Model\Product\Option\Value',
+            [
+                'resource' => $mockedResource,
+                'valueCollectionFactory' => $mockedCollectionFactory,
+                'context' => $mockedContext
+            ]
+        );
+        $this->model->setOption($this->getMockedOption());
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory
+     */
+    private function getMockedValueCollectionFactory()
+    {
+        $mockedCollection = $this->getMockedValueCollection();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($mockedCollection));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Resource\Product\Option\Value\Collection
+     */
+    private function getMockedValueCollection()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Option\Value\Collection')
+            ->setMethods(['addFieldToFilter', 'getValuesByOption', 'getValues'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('addFieldToFilter')
+            ->will($this->returnValue($mock));
+
+        $mock->expects($this->any())
+            ->method('getValuesByOption')
+            ->will($this->returnValue($mock));
+
+        $mock->expects($this->any())
+            ->method('getValues')
+            ->will($this->returnValue($mock));
+
+        return $mock;
+    }
+
+    /**
+     * @return Option
+     */
+    private function getMockedOption()
+    {
+        $mockedProduct = $this->getMockedProduct();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product\Option')
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getProduct')
+            ->will($this->returnValue($mockedProduct));
+
+        return $mock;
+    }
+
+    /**
+     * @return Product
+     */
+    private function getMockedProduct()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->setMethods(['getFinalPrice', '__wakeup'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getFinalPrice')
+            ->will($this->returnValue(10));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Resource\Product\Option\Value
+     */
+    private function getMockedResource()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Option\Value')
+            ->setMethods(
+                [
+                    'duplicate',
+                    '__wakeup',
+                    'getIdFieldName',
+                    'deleteValues',
+                    'deleteValue',
+                    'beginTransaction',
+                    'delete',
+                    'commit',
+                    'save',
+                    'addCommitCallback'
+                ]
+            )
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('duplicate');
+
+        $mock->expects($this->any())
+            ->method('deleteValues');
+
+        $mock->expects($this->any())
+            ->method('deleteValue');
+
+        $mock->expects($this->any())
+            ->method('delete');
+
+        $mock->expects($this->any())
+            ->method('save');
+
+        $mock->expects($this->any())
+            ->method('commit');
+
+        $mock->expects($this->any())
+            ->method('addCommitCallback')
+            ->will($this->returnValue($mock));
+
+        $mock->expects($this->any())
+            ->method('beginTransaction');
+
+        $mock->expects($this->any())
+            ->method('getIdFieldName')
+            ->will($this->returnValue('testField'));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Framework\Model\Context
+     */
+    private function getMockedContext()
+    {
+        $mockedRemoveAction = $this->getMockedRemoveAction();
+        $mockEventManager = $this->getMockedEventManager();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Model\Context')
+            ->setMethods(['getActionValidator', 'getEventDispatcher'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('getActionValidator')
+            ->will($this->returnValue($mockedRemoveAction));
+
+        $mock->expects($this->any())
+            ->method('getEventDispatcher')
+            ->will($this->returnValue($mockEventManager));
+
+        return $mock;
+    }
+
+    /**
+     * @return RemoveAction
+     */
+    private function getMockedRemoveAction()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Model\Context')
+            ->setMethods(['isAllowed'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('isAllowed')
+            ->will($this->returnValue(true));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Framework\Event\ManagerInterface
+     */
+    private function getMockedEventManager()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Event\ManagerInterface')
+            ->setMethods(['dispatch'])
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('dispatch');
+
+        return $mock;
+    }
+} 
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
index ed1c874538e..a82eef9c32f 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/Type/AbstractTypeTest.php
@@ -23,23 +23,131 @@
  */
 namespace Magento\Catalog\Model\Product\Type;
 
+use Magento\Catalog\Model\Product\Attribute\Source\Status;
+use Magento\TestFramework\Helper\ObjectManager;
+
 class AbstractTypeTest extends \PHPUnit_Framework_TestCase
 {
-    public function testHasOptions()
+    /**
+     * @var ObjectManager
+     */
+    private $objectManagerHelper;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Type\Simple|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $model;
+
+    /**
+     * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $product;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $productResource;
+
+    /**
+     * @var \Magento\Catalog\Model\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $attribute;
+
+    protected function setUp()
+    {
+        $this->objectManagerHelper = new ObjectManager($this);
+        $this->model = $this->objectManagerHelper->getObject('Magento\Catalog\Model\Product\Type\Simple');
+
+        $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product')
+            ->setMethods(['getHasOptions', '__wakeup', '__sleep', 'getResource'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->productResource = $this->getMockBuilder('Magento\Catalog\Model\Resource\Product')
+            ->setMethods(['getSortedAttributes', 'loadAllAttributes'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->product->expects($this->any())->method('getResource')->will($this->returnValue($this->productResource));
+
+        $this->attribute = $this->getMockBuilder('Magento\Catalog\Model\Entity\Attribute')
+            ->setMethods(['getGroupSortPath', 'getSortPath', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    public function testIsSalable()
     {
-        $objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->product->expects($this->any())->method('getStatus')->will(
+            $this->returnValue(Status::STATUS_ENABLED)
+        );
+        $this->product->setData('is_salable', 3);
+        $this->assertEquals(true, $this->model->isSalable($this->product));
+    }
 
-        $product = $this->getMock(
-            'Magento\Catalog\Model\Product',
-            array('getHasOptions', '__wakeup', '__sleep'),
-            array(),
-            '',
-            false
+    public function testGetAttributeById()
+    {
+        $this->productResource->expects($this->any())->method('loadAllAttributes')->will(
+            $this->returnValue($this->productResource)
+        );
+        $this->productResource->expects($this->any())->method('getSortedAttributes')->will(
+            $this->returnValue([$this->attribute])
         );
-        $product->expects($this->once())->method('getHasOptions')->will($this->returnValue(true));
+        $this->attribute->setId(1);
 
-        /** @var \Magento\Catalog\Model\Product\Type\Simple $model */
-        $model = $objectHelper->getObject('Magento\Catalog\Model\Product\Type\Simple');
-        $this->assertEquals(true, $model->hasOptions($product));
+        $this->assertEquals($this->attribute, $this->model->getAttributeById(1, $this->product));
+        $this->assertNull($this->model->getAttributeById(0, $this->product));
+    }
+
+    public function testGetEditableAttributes()
+    {
+        $expected = [$this->attribute];
+        $this->productResource->expects($this->any())->method('loadAllAttributes')->will(
+            $this->returnValue($this->productResource)
+        );
+        $this->productResource->expects($this->any())->method('getSortedAttributes')->will(
+            $this->returnValue($expected)
+        );
+        $this->assertEquals($expected, $this->model->getEditableAttributes($this->product));
+    }
+
+    /**
+     * @dataProvider attributeCompareProvider
+     */
+    public function testAttributesCompare($attr1, $attr2, $expectedResult)
+    {
+        $attribute = $this->attribute;
+        $attribute->expects($this->any())->method('getSortPath')->will($this->returnValue(1));
+
+        $attribute2 = clone $attribute;
+
+        $attribute->expects($this->any())->method('getGroupSortPath')->will($this->returnValue($attr1));
+        $attribute2->expects($this->any())->method('getGroupSortPath')->will($this->returnValue($attr2));
+
+        $this->assertEquals($expectedResult, $this->model->attributesCompare($attribute, $attribute2));
+    }
+
+    public function attributeCompareProvider()
+    {
+        return [
+            [2, 2, 0],
+            [2, 1, 1],
+            [1, 2, -1]
+        ];
+    }
+
+    public function testGetSetAttributes()
+    {
+        $this->productResource->expects($this->any())->method('loadAllAttributes')->will(
+            $this->returnValue($this->productResource)
+        );
+        $this->productResource->expects($this->any())->method('getSortedAttributes')->will($this->returnValue(5));
+        $this->model->getSetAttributes($this->product);
+        $this->assertEquals(5, $this->model->getSetAttributes($this->product));
+    }
+
+    public function testHasOptions()
+    {
+        $this->product->expects($this->once())->method('getHasOptions')->will($this->returnValue(true));
+        $this->assertEquals(true, $this->model->hasOptions($this->product));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/TypeTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/TypeTest.php
index a4ef7b477c8..af0a052b5df 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/TypeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/TypeTest.php
@@ -23,6 +23,13 @@
  */
 namespace Magento\Catalog\Model\Product;
 
+use Magento\Framework\Object;
+
+/**
+ * ProductType Test
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class TypeTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -38,8 +45,13 @@ class TypeTest extends \PHPUnit_Framework_TestCase
     protected $_productTypes = array(
         'type_id_1' => array('label' => 'label_1'),
         'type_id_2' => array('label' => 'label_2'),
-        'type_id_3' => array('label' => 'label_3', 'model' => 'some_model', 'composite' => 'some_type'),
-        'type_id_4' => array('label' => 'label_4', 'composite' => false)
+        'type_id_3' => array(
+            'label' => 'label_3',
+            'model' => 'some_model',
+            'composite' => 'some_type',
+            'price_model' => 'some_model'
+        ),
+        'simple' => array('label' => 'label_4', 'composite' => false)
     );
 
     /**
@@ -47,19 +59,6 @@ class TypeTest extends \PHPUnit_Framework_TestCase
      */
     protected $_model;
 
-    protected function setUp()
-    {
-        $this->_objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $config = $this->getMock('Magento\Catalog\Model\ProductTypes\ConfigInterface');
-
-        $config->expects($this->any())->method('getAll')->will($this->returnValue($this->_productTypes));
-
-        $this->_model = $this->_objectHelper->getObject(
-            'Magento\Catalog\Model\Product\Type',
-            array('config' => $config)
-        );
-    }
-
     public function testGetTypes()
     {
         $property = new \ReflectionProperty($this->_model, '_types');
@@ -70,36 +69,40 @@ class TypeTest extends \PHPUnit_Framework_TestCase
 
     public function testGetOptionArray()
     {
-        $this->assertEquals($this->_getOptions(), $this->_model->getOptionArray());
+        $this->assertEquals($this->getOptionArray(), $this->_model->getOptionArray());
     }
 
-    /**
-     * @return array
-     */
-    protected function _getOptions()
+    public function testGetAllOptions()
     {
-        $options = array();
-        foreach ($this->_productTypes as $typeId => $type) {
-            $options[$typeId] = __($type['label']);
+        $res[] = array('value' => '', 'label' => '');
+        foreach ($this->getOptionArray() as $index => $value) {
+            $res[] = array('value' => $index, 'label' => $value);
         }
-        return $options;
+        $this->assertEquals($res, $this->_model->getAllOptions());
     }
 
-    public function testGetAllOption()
+    public function testGetOptions()
     {
-        $res[] = array('value' => '', 'label' => '');
-        foreach ($this->_getOptions() as $index => $value) {
-            $res[] = array('value' => $index, 'label' => $value);
+        $res = [];
+        foreach ($this->getOptionArray() as $index => $value) {
+            $res[] = ['value' => $index, 'label' => $value];
         }
-        $this->assertEquals($res, $this->_model->getAllOptions());
+        $this->assertEquals($res, $this->_model->getOptions());
+    }
+
+    public function testGetAllOption()
+    {
+        $options = $this->getOptionArray();
+        array_unshift($options, array('value' => '', 'label' => ''));
+        $this->assertEquals($options, $this->_model->getAllOption());
     }
 
     public function testGetOptionText()
     {
-        $options = $this->_getOptions();
+        $options = $this->getOptionArray();
         $this->assertEquals($options['type_id_3'], $this->_model->getOptionText('type_id_3'));
         $this->assertEquals($options['type_id_1'], $this->_model->getOptionText('type_id_1'));
-        $this->assertNotEquals($options['type_id_1'], $this->_model->getOptionText('type_id_4'));
+        $this->assertNotEquals($options['type_id_1'], $this->_model->getOptionText('simple'));
         $this->assertNull($this->_model->getOptionText('not_exist'));
     }
 
@@ -120,11 +123,250 @@ class TypeTest extends \PHPUnit_Framework_TestCase
             $options[$typeId] = $type;
         }
 
-        $expected['type_id_4'] = $options['type_id_4'];
+        $expected['simple'] = $options['simple'];
         $expected['type_id_2'] = $options['type_id_2'];
         $expected['type_id_1'] = $options['type_id_1'];
         $expected['type_id_3'] = $options['type_id_3'];
 
         $this->assertEquals($expected, $this->_model->getTypesByPriority());
     }
+
+    public function testGetPriceInfo()
+    {
+        $mockedProduct = $this->getMockedProduct();
+        $expectedResult = '\Magento\Framework\Pricing\PriceInfoInterface';
+        $this->assertInstanceOf($expectedResult, $this->_model->getPriceInfo($mockedProduct));
+    }
+
+    public function testFactory()
+    {
+        $mockedProduct = $this->getMockedProduct();
+
+        $mockedProduct->expects($this->at(0))
+            ->method('getTypeId')
+            ->will($this->returnValue('type_id_1'));
+        $mockedProduct->expects($this->at(1))
+            ->method('getTypeId')
+            ->will($this->returnValue('type_id_3'));
+
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Product\Type\Simple',
+            $this->_model->factory($mockedProduct)
+        );
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Product\Type\Virtual',
+            $this->_model->factory($mockedProduct)
+        );
+    }
+
+    public function testPriceFactory()
+    {
+        $this->assertInstanceOf(
+            '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price',
+            $this->_model->priceFactory('type_id_3')
+        );
+        $this->assertInstanceOf(
+            '\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price',
+            $this->_model->priceFactory('type_id_3')
+        );
+        $this->assertInstanceOf(
+            '\Magento\Catalog\Model\Product\Type\Price',
+            $this->_model->priceFactory('type_id_1')
+        );
+    }
+
+    protected function setUp()
+    {
+        $this->_objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $mockedPriceInfoFactory = $this->getMockedPriceInfoFactory();
+        $mockedProductTypePool = $this->getMockedProductTypePool();
+        $mockedConfig = $this->getMockedConfig();
+        $mockedTypePriceFactory = $this->getMockedTypePriceFactory();
+
+        $this->_model = $this->_objectHelper->getObject(
+            'Magento\Catalog\Model\Product\Type',
+            [
+                'config' => $mockedConfig,
+                'priceInfoFactory' => $mockedPriceInfoFactory,
+                'productTypePool' => $mockedProductTypePool,
+                'priceFactory' => $mockedTypePriceFactory
+            ]
+        );
+    }
+
+    /**
+     * @return array
+     */
+    protected function getOptionArray()
+    {
+        $options = [];
+        foreach ($this->_productTypes as $typeId => $type) {
+            $options[$typeId] = __($type['label']);
+        }
+        return $options;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product
+     */
+    private function getMockedProduct()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product')
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMock();
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Framework\Pricing\PriceInfo\Factory
+     */
+    private function getMockedPriceInfoFactory()
+    {
+        $mockedPriceInfoInterface = $this->getMockedPriceInfoInterface();
+
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Pricing\PriceInfo\Factory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create']);
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($mockedPriceInfoInterface));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Framework\Pricing\PriceInfoInterface
+     */
+    private function getMockedPriceInfoInterface()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Framework\Pricing\PriceInfoInterface')
+            ->disableOriginalConstructor();
+        $mock = $mockBuilder->getMockForAbstractClass();
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product\Type\Pool
+     */
+    private function getMockedProductTypePool()
+    {
+        $mockBuild = $this->getMockBuilder('\Magento\Catalog\Model\Product\Type\Pool')
+            ->disableOriginalConstructor()
+            ->setMethods(['get']);
+        $mock = $mockBuild->getMock();
+
+        $mock->expects($this->any())
+            ->method('get')
+            ->will(
+                $this->returnValueMap(
+                    [
+                        ['some_model', [], $this->getMockedProductTypeVirtual()],
+                        ['Magento\Catalog\Model\Product\Type\Simple', [], $this->getMockedProductTypeSimple()]
+                    ]
+                )
+            );
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product\Type\Virtual
+     */
+    private function getMockedProductTypeVirtual()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product\Type\Virtual')
+            ->disableOriginalConstructor()
+            ->setMethods(['setConfig']);
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('setConfig');
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product\Type\Simple
+     */
+    private function getMockedProductTypeSimple()
+    {
+        $mockBuilder = $this->getMockBuilder('\Magento\Catalog\Model\Product\Type\Simple')
+            ->disableOriginalConstructor()
+            ->setMethods(['setConfig']);
+        $mock = $mockBuilder->getMock();
+
+        $mock->expects($this->any())
+            ->method('setConfig');
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\ProductTypes\ConfigInterface
+     */
+    private function getMockedConfig()
+    {
+        $mockBuild = $this->getMockBuilder('\Magento\Catalog\Model\ProductTypes\ConfigInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(['getAll']);
+        $mock = $mockBuild->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('getAll')
+            ->will($this->returnValue($this->_productTypes));
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product\Type\Price\Factory
+     */
+    private function getMockedTypePriceFactory()
+    {
+        $mockBuild = $this->getMockBuilder('\Magento\Catalog\Model\Product\Type\Price\Factory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create']);
+        $mock = $mockBuild->getMockForAbstractClass();
+
+        $mock->expects($this->any())
+            ->method('create')
+            ->will(
+                $this->returnValueMap(
+                    [
+                        ['some_model', [], $this->getMockedProductTypeConfigurablePrice()],
+                        ['Magento\Catalog\Model\Product\Type\Price', [], $this->getMockedProductTypePrice()]
+                    ]
+                )
+            );
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\Catalog\Model\Product\Type\Price
+     */
+    private function getMockedProductTypePrice()
+    {
+        $mockBuild = $this->getMockBuilder('\Magento\Catalog\Model\Product\Type\Price')
+            ->disableOriginalConstructor();
+        $mock = $mockBuild->getMock();
+
+        return $mock;
+    }
+
+    /**
+     * @return \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price
+     */
+    private function getMockedProductTypeConfigurablePrice()
+    {
+        $mockBuild = $this->getMockBuilder('\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price')
+            ->disableOriginalConstructor();
+        $mock = $mockBuild->getMock();
+
+        return $mock;
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductTest.php
index c66ff5fe315..0ee7ff05b41 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductTest.php
@@ -25,6 +25,12 @@ namespace Magento\Catalog\Model;
 
 use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
 
+/**
+ * Product Test
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ *
+ */
 class ProductTest extends \PHPUnit_Framework_TestCase
 {
     /** @var ObjectManagerHelper */
@@ -65,6 +71,39 @@ class ProductTest extends \PHPUnit_Framework_TestCase
      */
     protected $_priceInfoMock;
 
+    /**
+     * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $store;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Product|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $resource;
+
+    /**
+     * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $registry;
+
+    /**
+     * @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $category;
+
+    /**
+     * @var \Magento\Catalog\Model\CategoryFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $categoryFactory;
+
+    /**
+     * @var \Magento\Store\Model\Website|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $website;
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
     public function setUp()
     {
         $this->categoryIndexerMock = $this->getMockForAbstractClass('\Magento\Indexer\Model\IndexerInterface');
@@ -120,6 +159,41 @@ class ProductTest extends \PHPUnit_Framework_TestCase
             ->setMethods(['setProduct', 'saveOptions', '__wakeup', '__sleep'])
             ->disableOriginalConstructor()->getMock();
 
+        $this->resource = $this->getMockBuilder('Magento\Catalog\Model\Resource\Product')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->registry = $this->getMockBuilder('Magento\Framework\Registry')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->category = $this->getMockBuilder('Magento\Catalog\Model\Category')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->categoryFactory = $this->getMockBuilder('Magento\Catalog\Model\CategoryFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->store = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->website = $this->getMockBuilder('\Magento\Store\Model\Website')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $storeManager->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($this->store));
+        $storeManager->expects($this->any())
+            ->method('getWebsite')
+            ->will($this->returnValue($this->website));
+
         $this->objectManagerHelper = new ObjectManagerHelper($this);
         $this->model = $this->objectManagerHelper->getObject(
             'Magento\Catalog\Model\Product',
@@ -130,11 +204,115 @@ class ProductTest extends \PHPUnit_Framework_TestCase
                 'productFlatIndexerProcessor' => $this->productFlatProcessor,
                 'productPriceIndexerProcessor' => $this->productPriceProcessor,
                 'catalogProductOption' => $this->optionInstanceMock,
+                'storeManager' => $storeManager,
+                'resource' => $this->resource,
+                'registry' => $this->registry,
+                'categoryFactory' => $this->categoryFactory,
                 'data' => array('id' => 1)
             ]
         );
     }
 
+    public function testGetAttributes()
+    {
+        $productType = $this->getMockBuilder('Magento\Catalog\Model\Product\Type\AbstractType')
+            ->setMethods(['getEditableAttributes'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $this->productTypeInstanceMock->expects($this->any())->method('factory')->will(
+            $this->returnValue($productType)
+        );
+        $attribute = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->setMethods(['__wakeup', 'isInGroup'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $attribute->expects($this->any())->method('isInGroup')->will($this->returnValue(true));
+        $productType->expects($this->any())->method('getEditableAttributes')->will(
+            $this->returnValue([$attribute])
+        );
+        $expect = [$attribute];
+        $this->assertEquals($expect, $this->model->getAttributes(5));
+        $this->assertEquals($expect, $this->model->getAttributes());
+    }
+
+    public function testGetStoreIds()
+    {
+        $expectedStoreIds = [1, 2, 3];
+        $websiteIds = ['test'];
+        $this->resource->expects($this->once())->method('getWebsiteIds')->will($this->returnValue($websiteIds));
+        $this->website->expects($this->once())->method('getStoreIds')->will($this->returnValue($expectedStoreIds));
+        $this->assertEquals($expectedStoreIds, $this->model->getStoreIds());
+    }
+
+    public function testGetStoreId()
+    {
+        $this->model->setStoreId(3);
+        $this->assertEquals(3, $this->model->getStoreId());
+        $this->model->unsStoreId();
+        $this->store->expects($this->once())->method('getId')->will($this->returnValue(5));
+        $this->assertEquals(5, $this->model->getStoreId());
+    }
+
+    public function testGetWebsiteIds()
+    {
+        $expected = ['test'];
+        $this->resource->expects($this->once())->method('getWebsiteIds')->will($this->returnValue($expected));
+        $this->assertEquals($expected, $this->model->getWebsiteIds());
+    }
+
+    public function testGetCategoryCollection()
+    {
+        $collection = $this->getMockBuilder('\Magento\Framework\Data\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->resource->expects($this->once())->method('getCategoryCollection')->will($this->returnValue($collection));
+        $this->assertInstanceOf('\Magento\Framework\Data\Collection', $this->model->getCategoryCollection());
+    }
+
+    public function testGetCategory()
+    {
+        $this->category->expects($this->any())->method('getId')->will($this->returnValue(10));
+        $this->registry->expects($this->any())->method('registry')->will($this->returnValue($this->category));
+        $this->categoryFactory->expects($this->any())->method('create')->will($this->returnValue($this->category));
+        $this->category->expects($this->once())->method('load')->will($this->returnValue($this->category));
+        $this->assertInstanceOf('\Magento\Catalog\Model\Category', $this->model->getCategory());
+    }
+
+    public function testGetCategoryId()
+    {
+        $this->category->expects($this->once())->method('getId')->will($this->returnValue(10));
+
+        $this->registry->expects($this->at(0))->method('registry');
+        $this->registry->expects($this->at(1))->method('registry')->will($this->returnValue($this->category));
+        $this->assertFalse($this->model->getCategoryId());
+        $this->assertEquals(10, $this->model->getCategoryId());
+    }
+
+    public function testGetIdBySku()
+    {
+        $this->resource->expects($this->once())->method('getIdBySku')->will($this->returnValue(5));
+        $this->assertEquals(5, $this->model->getIdBySku('someSku'));
+    }
+
+    public function testGetCategoryIds()
+    {
+        $this->model->lockAttribute('category_ids');
+        $this->assertEquals([], $this->model->getCategoryIds());
+    }
+
+    public function testGetStatus()
+    {
+        $this->model->setStatus(null);
+        $expected = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED;
+        $this->assertEquals($expected, $this->model->getStatus());
+    }
+
+    public function testIsInStock()
+    {
+        $this->model->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
+        $this->assertTrue($this->model->isInStock());
+    }
+
     public function testIndexerAfterDeleteCommitProduct()
     {
         $this->categoryIndexerMock->expects($this->once())->method('reindexRow');
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilderTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilderTest.php
index dc3da1419e7..7129c4a4a30 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilderTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilderTest.php
@@ -36,11 +36,17 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Catalog\Service\V1\Data\Eav\ValidationRuleBuilder */
     private $validationRuleBuilderMock;
 
+    /** @var \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabelBuilder */
+    private $frontendLabelBuilderMock;
+
     /** @var \Magento\Catalog\Service\V1\Data\Eav\ValidationRule[] */
-    protected $validationRules;
+    private $validationRules;
 
     /** @var \Magento\Catalog\Service\V1\Data\Eav\Option[] */
-    protected $optionRules;
+    private $optionRules;
+
+    /** @var \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel[] */
+    private $frontendLabels;
 
     protected function setUp()
     {
@@ -52,6 +58,11 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
         $this->validationRuleBuilderMock =
             $this->getMock('Magento\Catalog\Service\V1\Data\Eav\ValidationRuleBuilder', [], [], '', false);
 
+        $this->frontendLabelBuilderMock =
+            $this->getMock(
+                'Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabelBuilder', [], [], '', false
+            );
+
         $this->validationRules = array(
             [0 => $this->getMock('Magento\Catalog\Service\V1\Data\Eav\ValidationRule', [], [], '', false)],
             [1 => $this->getMock('Magento\Catalog\Service\V1\Data\Eav\ValidationRule', [], [], '', false)]
@@ -62,11 +73,25 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
             [1 => $this->getMock('Magento\Catalog\Service\V1\Data\Eav\Option', [], [], '', false)]
         );
 
+        $this->frontendLabels = array(
+            [
+                0 => $this->getMock(
+                    'Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel', [], [], '', false
+                )
+            ],
+            [
+                0 => $this->getMock(
+                    'Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel', [], [], '', false
+                )
+            ],
+        );
+
         $this->attributeMetadataBuilder = $objectManager->getObject(
             'Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder',
             [
                 'optionBuilder' => $this->optionBuilderMock,
-                'validationRuleBuilder' => $this->validationRuleBuilderMock
+                'validationRuleBuilder' => $this->validationRuleBuilderMock,
+                'frontendLabelBuilder' => $this->frontendLabelBuilderMock,
             ]
         );
     }
@@ -90,7 +115,7 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
             ['setRequired', true, 'isRequired'],
             ['setOptions', $this->optionRules, 'getOptions'],
             ['setUserDefined', false, 'isUserDefined'],
-            ['setFrontendLabel', 'Label', 'getFrontendLabel'],
+            ['setFrontendLabel', $this->frontendLabels, 'getFrontendLabel'],
             ['setFrontendClass', 'Class', 'getFrontendClass'],
             ['setNote', 'Text Note', 'getNote'],
         );
@@ -136,9 +161,29 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
             ->method('create')
             ->will($this->returnValue($this->validationRules[1]));
 
+        $this->frontendLabelBuilderMock
+            ->expects($this->at(0))
+            ->method('populateWithArray')
+            ->with($this->frontendLabels[0])
+            ->will($this->returnSelf());
+        $this->frontendLabelBuilderMock
+            ->expects($this->at(1))
+            ->method('create')
+            ->will($this->returnValue($this->frontendLabels[0]));
+        $this->frontendLabelBuilderMock
+            ->expects($this->at(2))
+            ->method('populateWithArray')
+            ->with($this->frontendLabels[1])
+            ->will($this->returnSelf());
+        $this->frontendLabelBuilderMock
+            ->expects($this->at(3))
+            ->method('create')
+            ->will($this->returnValue($this->frontendLabels[1]));
+
         $data = array(
             AttributeMetadata::OPTIONS => $this->optionRules,
             AttributeMetadata::VALIDATION_RULES => $this->validationRules,
+            AttributeMetadata::FRONTEND_LABEL => $this->frontendLabels,
             'note' => $textNote = 'Text Note',
             'visible' => $visible = true,
             'some_key' => 'some_value',
@@ -149,6 +194,7 @@ class AttributeMetadataBuilderTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($visible, $attributeData->isVisible());
         $this->assertEquals($data[AttributeMetadata::OPTIONS], $attributeData->getOptions());
         $this->assertEquals($data[AttributeMetadata::VALIDATION_RULES], $attributeData->getValidationRules());
+        $this->assertEquals($data[AttributeMetadata::FRONTEND_LABEL], $attributeData->getFrontendLabel());
         $this->assertArrayNotHasKey('some_key', $attributeData->__toArray());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataTest.php
index 5702ed54636..60efe1a446b 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataTest.php
@@ -101,12 +101,16 @@ class AttributeMetadataTest extends \PHPUnit_Framework_TestCase
         $validationRuleBuilder = $objectManager->getObject(
             'Magento\Catalog\Service\V1\Data\Eav\ValidationRuleBuilder'
         );
+        $frontendLabelBuilder = $objectManager->getObject(
+            'Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabelBuilder'
+        );
 
         $attributeBuilder = $objectManager->getObject(
             'Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder',
             [
                 'optionBuilder' => $optionBuilder,
-                'validationRuleBuilder' => $validationRuleBuilder
+                'validationRuleBuilder' => $validationRuleBuilder,
+                'frontendLabelBuilder' => $frontendLabelBuilder
             ]
         );
         $attributeBuilder->populateWithArray([AttributeMetadata::APPLY_TO => $applyTo]);
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceTest.php
new file mode 100644
index 00000000000..c64aaa43d35
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceTest.php
@@ -0,0 +1,255 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
+use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder;
+
+class ReadServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Test for retrieving product attributes types
+     */
+    public function testTypes()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $inputTypeFactoryMock = $this->getMock(
+            'Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory',
+            array('create')
+        );
+        $inputTypeFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue(
+                $objectManager->getObject('Magento\Catalog\Model\Product\Attribute\Source\Inputtype')
+            ));
+
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $attributeTypeBuilder = $helper->getObject(
+            '\Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\TypeBuilder'
+        );
+        $productAttributeReadService = $objectManager->getObject(
+            '\Magento\Catalog\Service\V1\Product\Attribute\ReadService',
+            [
+                'metadataService' => $objectManager->getObject('Magento\Catalog\Service\V1\ProductMetadataService'),
+                'inputTypeFactory' => $inputTypeFactoryMock,
+                'attributeTypeBuilder' => $attributeTypeBuilder
+            ]
+        );
+        $types = $productAttributeReadService->types();
+        $this->assertTrue(is_array($types));
+        $this->assertNotEmpty($types);
+        $this->assertInstanceOf('Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\Type', current($types));
+    }
+
+    /**
+     * Test for retrieving product attribute
+     */
+    public function testInfo()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $attributeCode = 'attr_code';
+        $metadataServiceMock = $this->getMock(
+            'Magento\Catalog\Service\V1\ProductMetadataService', array('getAttributeMetadata'),
+            array(),
+            '',
+            false
+        );
+        $metadataServiceMock->expects($this->once())
+            ->method('getAttributeMetadata')
+            ->with(
+                ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+                $attributeCode
+            );
+
+        /** @var \Magento\Catalog\Service\V1\Product\Attribute\ReadServiceInterface $service */
+        $service = $objectManager->getObject(
+            'Magento\Catalog\Service\V1\Product\Attribute\ReadService',
+            array(
+               'metadataService' => $metadataServiceMock
+            )
+        );
+        $service->info($attributeCode);
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function testSearch()
+    {
+        $attrCollectionMock = $this->getMock('Magento\Eav\Model\Resource\Entity\Attribute\Collection',
+            array(), array(), '', false);
+        $attrCollectionMock->expects($this->any())->method('addOrder')->with(
+            $this->equalTo('attribute_id'),
+            $this->equalTo('DESC')
+        );
+        $attrCollectionMock->expects($this->once())->method('getTable')->with(
+            $this->equalTo('catalog_eav_attribute')
+        )->will(
+            $this->returnValue('catalog_eav_attribute')
+        );
+        $attrCollectionMock->expects($this->once())->method('join')->with(
+            $this->equalTo(array('additional_table' => 'catalog_eav_attribute')),
+            $this->equalTo('main_table.attribute_id = additional_table.attribute_id'),
+            $this->equalTo(
+                [
+                    'frontend_input_renderer',
+                    'is_global',
+                    'is_visible',
+                    'is_searchable',
+                    'is_filterable',
+                    'is_comparable',
+                    'is_visible_on_front',
+                    'is_html_allowed_on_front',
+                    'is_used_for_price_rules',
+                    'is_filterable_in_search',
+                    'used_in_product_listing',
+                    'used_for_sort_by',
+                    'apply_to',
+                    'is_visible_in_advanced_search',
+                    'position',
+                    'is_wysiwyg_enabled',
+                    'is_used_for_promo_rules',
+                    'is_configurable',
+                    'search_weight',
+                ]
+            )
+        );
+        $attrCollectionMock->expects($this->once())->method('getSize')->will($this->returnValue(1));
+        $attrCollectionMock->expects($this->once())->method('addFieldToFilter')->with(
+            $this->equalTo(array('frontend_input')),
+            $this->equalTo(array(array('eq' => 'text')))
+        );
+
+        $attributeData = array(
+            'attribute_id' => 1,
+            'attribute_code' => 'status',
+            'frontend_label' => 'Status',
+            'default_value' => '1',
+            'is_required' => false,
+            'is_user_defined' => false,
+            'frontend_input' => 'text'
+        );
+        // Use magento object for simplicity
+        $attributeElement = new \Magento\Framework\Object($attributeData);
+        $this->_mockReturnValue(
+            $attrCollectionMock,
+            array(
+                'getSize' => 1,
+                '_getItems' => array($attributeElement),
+                'getIterator' => new \ArrayIterator(array($attributeElement))
+            )
+        );
+
+        $attributeBuilderMock = $this->getMock('\Magento\Catalog\Service\V1\Data\Eav\AttributeBuilder',
+            array(), array(), '', false);
+
+        $attributeBuilderMock->expects($this->once())
+            ->method('setId')
+            ->with($attributeData['attribute_id'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setCode')
+            ->with($attributeData['attribute_code'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setFrontendLabel')
+            ->with($attributeData['frontend_label'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setDefaultValue')
+            ->with($attributeData['default_value'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setIsRequired')
+            ->with($attributeData['is_required'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setIsUserDefined')
+            ->with($attributeData['is_user_defined'])
+            ->will($this->returnSelf());
+        $attributeBuilderMock->expects($this->once())
+            ->method('setFrontendInput')
+            ->with($attributeData['frontend_input'])
+            ->will($this->returnSelf());
+
+        $dataObjectMock = $this->getMock(
+            '\Magento\Catalog\Service\V1\Data\Eav\Attribute',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $attributeBuilderMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($dataObjectMock));
+
+        $searchResultsBuilderMock = $this->getMockBuilder(
+                'Magento\Catalog\Service\V1\Data\Product\Attribute\SearchResultsBuilder'
+            )->disableOriginalConstructor()
+            ->getMock();
+
+        $searchResultsBuilderMock->expects($this->once())
+            ->method('setItems')
+            ->with($this->equalTo(array($dataObjectMock)));
+        $searchResultsBuilderMock->expects($this->once())
+            ->method('create');
+
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $filterBuilder = $helper->getObject('Magento\Framework\Service\V1\Data\FilterBuilder');
+        $filter = $filterBuilder->setField('frontend_input')->setValue('text')->setConditionType('eq')->create();
+
+        $filterGroupBuilder = $helper->getObject('Magento\Framework\Service\V1\Data\Search\FilterGroupBuilder');
+        /** @var SearchCriteriaBuilder $searchBuilder */
+        $searchBuilder = $helper->getObject(
+            'Magento\Framework\Service\V1\Data\SearchCriteriaBuilder',
+            ['filterGroupBuilder' => $filterGroupBuilder]
+        );
+        $searchBuilder->addFilter([$filter]);
+        $searchBuilder->addSortOrder('id', \Magento\Framework\Service\V1\Data\SearchCriteria::SORT_DESC);
+        $searchBuilder->setCurrentPage(1);
+        $searchBuilder->setPageSize(10);
+
+        $prductAttrService = $helper->getObject(
+            'Magento\Catalog\Service\V1\Product\Attribute\ReadService',
+            [
+                'searchResultsBuilder' => $searchResultsBuilderMock,
+                'attributeCollection' => $attrCollectionMock,
+                'attributeBuilder' => $attributeBuilderMock
+            ]
+        );
+        $prductAttrService->search($searchBuilder->create());
+    }
+
+    /**
+     * @param \PHPUnit_Framework_MockObject_MockObject $mock
+     * @param array $valueMap
+     */
+    private function _mockReturnValue($mock, $valueMap)
+    {
+        foreach ($valueMap as $method => $value) {
+            $mock->expects($this->any())->method($method)->will($this->returnValue($value));
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceTest.php
new file mode 100644
index 00000000000..9a2d0e66a0a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceTest.php
@@ -0,0 +1,293 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1\Product\Attribute;
+
+use Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata;
+use Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder;
+use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
+use Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel;
+
+class WriteServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder
+     */
+    protected $attributeMetadataBuilder;
+
+    /**
+     * @var \Magento\Catalog\Model\Resource\Eav\Attribute | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $attributeMock;
+
+    /**
+     * @var \Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator
+     */
+    protected $inputValidator;
+
+    /**
+     * @var \Magento\Eav\Model\Config | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eavConfig;
+
+    /**
+     * @var FrontendLabel | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $frontendLabelMock;
+
+    /**
+     * @var \Magento\Catalog\Service\V1\Product\Attribute\WriteService
+     */
+    protected $attributeWriteService;
+
+    /**
+     * @var int
+     */
+    protected $typeId = 4;
+
+    public function setUp()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->attributeMetadataBuilder = $objectManager
+            ->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder');
+
+        $this->attributeMock = $this->getMock('\Magento\Catalog\Model\Resource\Eav\Attribute', [], [], '', false);
+        $attributeFactory =
+            $this->getMock('\Magento\Catalog\Model\Resource\Eav\AttributeFactory', ['create'], [], '', false);
+        $attributeFactory
+            ->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->attributeMock));
+
+        $this->eavConfig = $this->getMock('\Magento\Eav\Model\Config', [], [], '', false);
+        $this->inputValidator =
+            $this->getMock('\Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator', [], [], '', false);
+        $inputValidatorFactory =
+            $this->getMock(
+                '\Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory',
+                ['create'], [], '', false
+            );
+        $inputValidatorFactory
+            ->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->inputValidator));
+
+        $this->frontendLabelMock = $this->getMock(
+            '\Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel', [], [], '', false
+        );
+        $this->frontendLabelMock->expects($this->any())
+            ->method('getStoreId')
+            ->will($this->returnValue(0));
+
+        $this->frontendLabelMock->expects($this->any())
+            ->method('getLabel')
+            ->will($this->returnValue('Default Label'));
+
+        $this->attributeWriteService = $objectManager->getObject(
+            '\Magento\Catalog\Service\V1\Product\Attribute\WriteService',
+            [
+                'eavConfig' => $this->eavConfig,
+                'attributeFactory' => $attributeFactory,
+                'inputtypeValidatorFactory' => $inputValidatorFactory
+            ]
+        );
+    }
+
+    /**
+     * @dataProvider createDataProvider
+     */
+    public function testCreate($attrCode)
+    {
+        $dataMock = $this->getMock('\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata', [], [], '', false);
+        $dataMock->expects($this->any())->method('getFrontendLabel')
+            ->will($this->returnValue([$this->frontendLabelMock]));
+        $dataMock->expects($this->any())->method('__toArray')->will($this->returnValue(array()));
+        $dataMock->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attrCode));
+        $dataMock->expects($this->any())->method('getFrontendInput')->will($this->returnValue('textarea'));
+        $this->inputValidator->expects($this->once())->method('isValid')->will($this->returnValue(true));
+        $this->attributeMock->expects($this->any())->method('setEntityTypeId')->will($this->returnSelf());
+        $this->attributeMock->expects($this->any())->method('save')->will($this->returnSelf());
+        $this->eavConfig
+            ->expects($this->once())
+            ->method('getEntityType')
+            ->with(\Magento\Catalog\Model\Product::ENTITY)
+            ->will($this->returnValue(new \Magento\Framework\Object()));
+
+        $this->attributeWriteService->create($dataMock);
+    }
+
+    /**
+     * @return array
+     */
+    public function createDataProvider()
+    {
+        return array(
+            ['code_111'],
+            [''] //cover generateCode()
+        );
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testCreateEmptyLabel()
+    {
+        $dataMock = $this->getMock('\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata', [], [], '', false);
+        $dataMock->expects($this->at(0))->method('getFrontendLabel')->will($this->returnValue([]));
+        $this->attributeWriteService->create($dataMock);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testCreateInvalidCode()
+    {
+        $dataMock = $this->getMock('\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata', [], [], '', false);
+        $dataMock->expects($this->at(0))->method('__toArray')->will($this->returnValue(array()));
+        $dataMock->expects($this->at(1))->method('getFrontendLabel')
+            ->will($this->returnValue([$this->frontendLabelMock]));
+        $dataMock->expects($this->at(2))->method('getFrontendLabel')
+            ->will($this->returnValue([$this->frontendLabelMock]));
+        $dataMock->expects($this->at(3))->method('getAttributeCode')->will($this->returnValue('111'));
+        $this->attributeWriteService->create($dataMock);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testCreateInvalidInput()
+    {
+        $dataMock = $this->getMock('\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata', [], [], '', false);
+        $dataMock->expects($this->at(0))->method('__toArray')->will($this->returnValue(array()));
+        $dataMock->expects($this->at(1))->method('getFrontendLabel')
+            ->will($this->returnValue([$this->frontendLabelMock]));
+        $dataMock->expects($this->at(2))->method('getFrontendLabel')
+            ->will($this->returnValue([$this->frontendLabelMock]));
+        $dataMock->expects($this->at(3))->method('getAttributeCode')->will($this->returnValue('code_111'));
+        $dataMock->expects($this->at(4))->method('getFrontendInput')->will($this->returnValue('textarea'));
+        $this->inputValidator->expects($this->at(0))->method('isValid')->will($this->returnValue(false));
+        $this->attributeWriteService->create($dataMock);
+    }
+
+    public function testUpdate()
+    {
+        $attributeObject = $this->getMockBuilder('\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $attributeCode = 'color';
+        $this->attributeMock
+            ->expects($this->at(0))
+            ->method('loadByCode')
+            ->with(
+                $this->equalTo(\Magento\Catalog\Model\Product::ENTITY),
+                $this->equalTo($attributeCode)
+            );
+
+        $attributeObject
+            ->expects($this->once())
+            ->method('__toArray')
+            ->will($this->returnValue(
+               [
+                   AttributeMetadata::FILTERABLE => 2,
+                   AttributeMetadata::FRONTEND_LABEL => [
+                       [
+                           'store_id' => 1,
+                           'label'    => 'Label for store 1'
+                       ],
+                   ],
+                   AttributeMetadata::APPLY_TO => [
+                       'simple',
+                       'virtual'
+                   ]
+               ]
+            ));
+
+
+        // check that methods will be called
+        $this->attributeMock->expects($this->at(1))->method('getId')->will($this->returnValue(1));
+        $this->attributeMock->expects($this->at(2))->method('getAttributeId')->will($this->returnValue(1));
+        // cover "getIsUserDefined" method - uses __call because "getIsUserDefined" magic method
+        $this->attributeMock->expects($this->at(3))->method('__call')->will($this->returnValue(true));
+        // cover "getFrontendInput" method - uses __call because "getFrontendInput" magic method
+        $this->attributeMock->expects($this->at(4))->method('__call')->will($this->returnValue('select'));
+        // cover "getFrontendLabel" method - uses __call because "getFrontendLabel" magic method
+        $this->attributeMock->expects($this->at(5))->method('__call')
+            ->will($this->returnValue('Label'));
+        // cover "getIsUserDefined" method - uses __call because "getIsUserDefined" magic method
+        // return false to check unset of element with "apply_to" key
+        $this->attributeMock->expects($this->at(6))->method('__call')->will($this->returnValue(false));
+        // absent of "apply_to" key also checks here - because of false in previous call
+        $this->attributeMock->expects($this->at(7))->method('addData')
+            ->with(
+                [
+                    'filterable'     => 2,
+                    'frontend_label' => [0 => 'Label', 1 => 'Label for store 1'],
+                    'attribute_id'   => 1,
+                    'user_defined'   => true,
+                    'frontend_input' => 'select'
+                ]
+            );
+
+        $this->attributeMock->expects($this->at(8))->method('save');
+        $this->attributeMock->expects($this->at(9))->method('getAttributeCode')
+            ->will($this->returnValue($attributeCode));
+
+        // run process
+        $this->attributeWriteService->update($attributeCode, $attributeObject);
+    }
+
+    /**
+     * Test for remove attribute
+     */
+    public function testRemove()
+    {
+        $id = 1;
+        $this->eavConfig
+            ->expects($this->once())
+            ->method('getAttribute')
+            ->with(ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, $id)
+            ->will($this->returnValue($this->attributeMock));
+        $this->attributeMock->expects($this->at(0))->method('getId')->will($this->returnValue(1));
+        $this->attributeMock->expects($this->at(1))->method('delete');
+        $this->assertTrue($this->attributeWriteService->remove($id));
+    }
+
+    /**
+     * Test for remove attribute
+     */
+    public function testRemoveNoSuchEntityException()
+    {
+        $id = -1;
+        $this->eavConfig
+            ->expects($this->once())
+            ->method('getAttribute')
+            ->with(ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, $id)
+            ->will($this->returnValue(false));
+        $this->setExpectedException(
+            'Magento\Framework\Exception\NoSuchEntityException',
+            "No such entity with attribute_id = $id"
+        );
+        $this->assertTrue($this->attributeWriteService->remove($id));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeSet/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeSet/ReadServiceTest.php
index f1c32d7fbea..e70af95fc31 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeSet/ReadServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeSet/ReadServiceTest.php
@@ -270,6 +270,7 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
             'default_value' => '1',
             'is_required' => false,
             'is_user_defined' => false,
+            'frontend_input' => 'text'
         );
 
         // Use magento object for simplicity
@@ -300,6 +301,10 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase
             ->method('setIsUserDefined')
             ->with($attributeData['is_user_defined'])
             ->will($this->returnSelf());
+        $this->attributeBuilderMock->expects($this->once())
+            ->method('setFrontendInput')
+            ->with($attributeData['frontend_input'])
+            ->will($this->returnSelf());
 
         $dataObjectMock = $this->getMock(
             '\Magento\Catalog\Service\V1\Data\Eav\Attribute',
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeReadServiceTest.php
deleted file mode 100644
index 544eb36d345..00000000000
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeReadServiceTest.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Catalog\Service\V1;
-
-use Magento\Catalog\Service\V1\Data\ProductAttributeTypeBuilder;
-use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
-
-class ProductAttributeReadServiceTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * Test for retrieving product attributes types
-     */
-    public function testTypes()
-    {
-        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $inputtypeFactoryMock = $this->getMock(
-            'Magento\Catalog\Model\Product\Attribute\Source\InputtypeFactory',
-            array('create')
-        );
-        $inputtypeFactoryMock->expects($this->once())
-            ->method('create')
-            ->will($this->returnValue(
-                $objectManager->getObject('Magento\Catalog\Model\Product\Attribute\Source\Inputtype')
-            ));
-
-        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $attributeTypeBuilder = $helper->getObject('\Magento\Catalog\Service\V1\Data\ProductAttributeTypeBuilder');
-        $productAttributeReadService = new ProductAttributeReadService(
-            $objectManager->getObject('Magento\Catalog\Service\V1\ProductMetadataService'),
-            $inputtypeFactoryMock,
-            $attributeTypeBuilder
-        );
-        $types = $productAttributeReadService->types();
-        $this->assertTrue(is_array($types));
-        $this->assertNotEmpty($types);
-        $this->assertInstanceOf('Magento\Catalog\Service\V1\Data\ProductAttributeType', current($types));
-    }
-
-    /**
-     * Test for retrieving product attribute
-     */
-    public function testInfo()
-    {
-        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-
-        $attributeCode = 'attr_code';
-        $metadataServiceMock = $this->getMock(
-            'Magento\Catalog\Service\V1\ProductMetadataService', array('getAttributeMetadata'),
-            array(),
-            '',
-            false
-        );
-        $metadataServiceMock->expects($this->once())
-            ->method('getAttributeMetadata')
-            ->with(
-                ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
-                $attributeCode
-            );
-
-        /** @var \Magento\Catalog\Service\V1\ProductAttributeReadServiceInterface $service */
-        $service = $objectManager->getObject(
-            'Magento\Catalog\Service\V1\ProductAttributeReadService',
-            array(
-               'metadataService' => $metadataServiceMock
-            )
-        );
-        $service->info($attributeCode);
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeServiceTest.php
new file mode 100644
index 00000000000..330c1c2979c
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductAttributeServiceTest.php
@@ -0,0 +1,176 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Catalog\Service\V1;
+
+use Magento\Catalog\Service\V1\ProductMetadataServiceInterface;
+
+class ProductAttributeServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Test for retrieving attribute options
+     */
+    public function testOptions()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $attributeCode = 'attr_code';
+        $metadataServiceMock = $this->getMock(
+            'Magento\Catalog\Service\V1\ProductMetadataService',
+            array('getAttributeMetadata'),
+            array(),
+            '',
+            false
+        );
+
+        $mock = $this->getMock(
+            'Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata',
+            array('getOptions'),
+            array(),
+            '',
+            false
+        );
+
+        $options = array();
+        $mock->expects($this->once())
+            ->method('getOptions')
+            ->will($this->returnValue($options));
+
+        $metadataServiceMock->expects($this->once())
+            ->method('getAttributeMetadata')
+            ->with(
+                ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+                $attributeCode
+            )
+            ->will($this->returnValue($mock));
+
+        /** @var \Magento\Catalog\Service\V1\ProductAttributeServiceInterface $service */
+        $service = $objectManager->getObject(
+            'Magento\Catalog\Service\V1\ProductAttributeService',
+            array(
+                'metadataService' => $metadataServiceMock
+            )
+        );
+        $this->assertEquals($options, $service->options($attributeCode));
+    }
+
+    /**
+     * Build label
+     *
+     * @param $labelText
+     * @param $storeId
+     * @return \Magento\Catalog\Service\V1\Data\Eav\Option\Label
+     */
+    private function buildLabel($labelText, $storeId)
+    {
+        $label = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\Eav\Option\Label')
+            ->disableOriginalConstructor()->getMock();
+
+        $label->expects($this->any())
+            ->method('getLabel')->will($this->returnValue($labelText));
+
+        $label->expects($this->any())
+            ->method('getStoreID')->will($this->returnValue($storeId));
+
+        return $label;
+    }
+
+    /**
+     * Test for retrieving attribute options
+     */
+    public function testAddOption()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $attributeCode = 'attr_code';
+
+        $label = $this->buildLabel('st 42', 42);
+
+        $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->disableOriginalConstructor()->getMock();
+        $attribute->expects($this->any())
+            ->method('usesSource')
+            ->will($this->returnValue(true));
+
+        $attribute->expects($this->at(1))
+            ->method('__call')
+            ->with('setDefault', [['new_option']]);
+
+        $attribute->expects($this->at(2))
+            ->method('__call')
+            ->with(
+                'setOption',
+                [
+                    [
+                        'value' => ['new_option' => ['label', 42 => 'st 42']],
+                        'order' => ['new_option' => 10],
+                    ]
+                ]
+            );
+
+        $attribute->expects($this->any())
+            ->method('save');
+
+        $option = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\Eav\Option')
+            ->disableOriginalConstructor()->getMock();
+
+        $option->expects($this->any())
+            ->method('getLabel')->will($this->returnValue('label'));
+
+        $option->expects($this->any())
+            ->method('getStoreLabels')
+            ->will(
+                $this->returnValue(
+                    [
+                        $label
+                    ]
+                )
+            );
+
+        $option->expects($this->any())
+            ->method('getOrder')->will($this->returnValue(10));
+
+        $option->expects($this->any())
+            ->method('isDefault')->will($this->returnValue(true));
+
+        $eavConfig = $this->getMockBuilder('Magento\Eav\Model\Config')
+            ->disableOriginalConstructor()->getMock();
+
+        $eavConfig->expects($this->any())
+            ->method('getAttribute')
+            ->with(
+                \Magento\Catalog\Service\V1\ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT,
+                $attributeCode
+            )->will($this->returnValue($attribute));
+
+        /** @var \Magento\Catalog\Service\V1\ProductAttributeServiceInterface $service */
+        $service = $objectManager->getObject(
+            'Magento\Catalog\Service\V1\ProductAttributeService',
+            array(
+                'eavConfig' => $eavConfig
+            )
+        );
+
+        $this->assertTrue($service->addOption($attributeCode, $option));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductMetadataServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductMetadataServiceTest.php
index 75b62b0db3c..7d18a38bb2e 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductMetadataServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductMetadataServiceTest.php
@@ -62,11 +62,14 @@ class ProductMetadataServiceTest extends \PHPUnit_Framework_TestCase
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
         $validationRuleBuilder = $helper->getObject('\Magento\Catalog\Service\V1\Data\Eav\ValidationRuleBuilder');
         $optionBuilder = $helper->getObject('\Magento\Catalog\Service\V1\Data\Eav\OptionBuilder');
+        $frontendLabelBuilder = $helper
+            ->getObject('\Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabelBuilder');
         $attrMetadataBuilder = $objectManager->getObject(
             'Magento\Catalog\Service\V1\Data\Eav\AttributeMetadataBuilder',
             [
                 'optionBuilder' => $optionBuilder,
-                'validationRuleBuilder' => $validationRuleBuilder
+                'validationRuleBuilder' => $validationRuleBuilder,
+                'frontendLabelBuilder' => $frontendLabelBuilder,
             ]
         );
 
@@ -83,7 +86,9 @@ class ProductMetadataServiceTest extends \PHPUnit_Framework_TestCase
         $this->assertInstanceOf('Magento\Framework\Service\Data\AbstractObject', $dto);
         $this->assertEquals($attributeMock->getFrontendInput(), $dto->getFrontendInput());
 
-        $this->assertTrue(is_array($dto->getFrontendLabel()));
-        $this->assertArrayHasKey('store_id', $dto->getFrontendLabel()[0]);
+        $this->assertEquals(0, $dto->getFrontendLabel()[0]->getStoreId());
+        $this->assertEquals(1, $dto->getFrontendLabel()[1]->getStoreId());
+        $this->assertEquals('English', $dto->getFrontendLabel()[0]->getLabel());
+        $this->assertEquals('France', $dto->getFrontendLabel()[1]->getLabel());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductServiceTest.php
index 339429f84b4..567c8bd6541 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/ProductServiceTest.php
@@ -53,7 +53,7 @@ class ProductServiceTest extends \PHPUnit_Framework_TestCase
     protected $_objectManager;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Catalog\Service\V1\Data\SearchResultsBuilder
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder
      */
     protected $searchResultsBuilderMock;
 
@@ -100,8 +100,9 @@ class ProductServiceTest extends \PHPUnit_Framework_TestCase
             ->setMethods(['create'])
             ->getMock();
 
-        $this->searchResultsBuilderMock = $this->getMockBuilder('Magento\Catalog\Service\V1\Data\SearchResultsBuilder')
-            ->disableOriginalConstructor()
+        $this->searchResultsBuilderMock = $this->getMockBuilder(
+                'Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder'
+            )->disableOriginalConstructor()
             ->getMock();
 
         $this->metadataServiceMock = $this->getMockBuilder(
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
similarity index 92%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
index 5e7ba9183ec..161c45ac6af 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php
@@ -21,12 +21,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity;
+namespace Magento\CatalogImportExport\Model\Export;
 
 class ProductTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var Stub_UnitTest_\Magento\ImportExport\Model\Export\Entity\Product
+     * @var Stub_UnitTest_\Magento\CatalogImportExport\Model\Export\Product
      */
     protected $_object;
 
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/StubProduct.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/StubProduct.php
similarity index 91%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/StubProduct.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/StubProduct.php
index 23c85a27364..89c8e490eb3 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Entity/StubProduct.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Export/StubProduct.php
@@ -21,9 +21,9 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Export\Entity;
+namespace Magento\CatalogImportExport\Model\Export;
 
-class StubProduct extends \Magento\ImportExport\Model\Export\Entity\Product
+class StubProduct extends \Magento\CatalogImportExport\Model\Export\Product
 {
     /**
      * Disable parent constructor
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/OptionTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
similarity index 90%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/OptionTest.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
index a0cf3c44c7b..e1293d81d92 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/OptionTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/OptionTest.php
@@ -21,12 +21,11 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+namespace Magento\CatalogImportExport\Model\Import\Product\Type;
 
 /**
  * Test class for import product options module
  */
-namespace Magento\ImportExport\Model\Import\Entity\Product;
-
 class OptionTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -64,14 +63,14 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     /**
      * Test entity
      *
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\Option
+     * @var \Magento\CatalogImportExport\Model\Import\Product\Option
      */
     protected $_model;
 
     /**
      * Parent product entity
      *
-     * @var \Magento\ImportExport\Model\Import\Entity\Product
+     * @var \Magento\CatalogImportExport\Model\Import\Product
      */
     protected $_productEntity;
 
@@ -239,7 +238,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
 
         $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
 
-        $this->_model = new \Magento\ImportExport\Model\Import\Entity\Product\Option(
+        $this->_model = new \Magento\CatalogImportExport\Model\Import\Product\Option(
             $this->getMock('Magento\ImportExport\Model\Resource\Import\Data', array(), array(), '', false),
             $this->getMock('Magento\Framework\App\Resource', array(), array(), '', false),
             $this->getMock('Magento\ImportExport\Model\Resource\Helper', array(), array(), '', false),
@@ -371,14 +370,14 @@ class OptionTest extends \PHPUnit_Framework_TestCase
                     'id' => $elementIndex,
                     'entity_id' => $elementIndex,
                     'product_id' => $elementIndex,
-                    'type' => $csvDataRow[\Magento\ImportExport\Model\Import\Entity\Product\Option::COLUMN_TYPE],
-                    'title' => $csvDataRow[\Magento\ImportExport\Model\Import\Entity\Product\Option::COLUMN_TITLE]
+                    'type' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product\Option::COLUMN_TYPE],
+                    'title' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product\Option::COLUMN_TITLE]
                 );
             }
         }
 
         $this->_productEntity = $this->getMock(
-            'Magento\ImportExport\Model\Import\Entity\Product',
+            'Magento\CatalogImportExport\Model\Import\Product',
             null,
             array(),
             '',
@@ -574,7 +573,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::getEntityTypeCode
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::getEntityTypeCode
      */
     public function testGetEntityTypeCode()
     {
@@ -582,15 +581,15 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::importData
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_importData
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveOptions
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveTitles
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_savePrices
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveSpecificTypeValues
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveSpecificTypePrices
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveSpecificTypeTitles
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_updateProducts
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::importData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_importData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveOptions
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveTitles
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_savePrices
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveSpecificTypeValues
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveSpecificTypePrices
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveSpecificTypeTitles
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_updateProducts
      */
     public function testImportDataAppendBehavior()
     {
@@ -598,8 +597,8 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_importData
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_deleteEntities
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_importData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_deleteEntities
      */
     public function testImportDataDeleteBehavior()
     {
@@ -648,7 +647,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
     /**
      * Test for validation of row without custom option
      *
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_isRowWithCustomOption
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_isRowWithCustomOption
      */
     public function testValidateRowNoCustomOption()
     {
@@ -662,15 +661,15 @@ class OptionTest extends \PHPUnit_Framework_TestCase
      * @param array $rowData
      * @param array $errors
      *
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::validateRow
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_isRowWithCustomOption
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_isMainOptionRow
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_isSecondaryOptionRow
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_validateMainRow
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_validateMainRowAdditionalData
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_validateSecondaryRow
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_validateSpecificTypeParameters
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_validateSpecificParameterData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::validateRow
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_isRowWithCustomOption
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_isMainOptionRow
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_isSecondaryOptionRow
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_validateMainRow
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_validateMainRowAdditionalData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_validateSecondaryRow
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_validateSpecificTypeParameters
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_validateSpecificParameterData
      * @dataProvider validateRowDataProvider
      */
     public function testValidateRow(array $rowData, array $errors)
@@ -691,11 +690,11 @@ class OptionTest extends \PHPUnit_Framework_TestCase
      * @param string|null $behavior
      * @param int $numberOfValidations
      *
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::validateAmbiguousData
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_findNewOptionsWithTheSameTitles
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_findOldOptionsWithTheSameTitles
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_findNewOldOptionsTypeMismatch
-     * @covers \Magento\ImportExport\Model\Import\Entity\Product\Option::_saveNewOptionData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::validateAmbiguousData
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_findNewOptionsWithTheSameTitles
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_findOldOptionsWithTheSameTitles
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_findNewOldOptionsTypeMismatch
+     * @covers \Magento\CatalogImportExport\Model\Import\Product\Option::_saveNewOptionData
      * @dataProvider validateAmbiguousDataDataProvider
      */
     public function testValidateAmbiguousData(
@@ -735,7 +734,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_invalid_store' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_invalid_store.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_STORE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_STORE => array(
                         array(1, null)
                     )
                 )
@@ -743,7 +742,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_incorrect_type' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_incorrect_type.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_TYPE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_TYPE => array(
                         array(1, null)
                     )
                 )
@@ -751,7 +750,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_no_title' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_no_title.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_EMPTY_TITLE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_EMPTY_TITLE => array(
                         array(1, null)
                     )
                 )
@@ -759,7 +758,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_empty_title' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_empty_title.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_EMPTY_TITLE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_EMPTY_TITLE => array(
                         array(1, null)
                     )
                 )
@@ -767,7 +766,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_invalid_price' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_invalid_price.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_PRICE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_PRICE => array(
                         array(1, null)
                     )
                 )
@@ -775,7 +774,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_invalid_max_characters' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_invalid_max_characters.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_MAX_CHARACTERS => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_MAX_CHARACTERS => array(
                         array(1, null)
                     )
                 )
@@ -783,7 +782,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_max_characters_less_zero' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_max_characters_less_zero.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_MAX_CHARACTERS => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_MAX_CHARACTERS => array(
                         array(1, null)
                     )
                 )
@@ -791,7 +790,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_invalid_sort_order' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_invalid_sort_order.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_SORT_ORDER => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_SORT_ORDER => array(
                         array(1, null)
                     )
                 )
@@ -799,7 +798,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'main_sort_order_less_zero' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_sort_order_less_zero.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_SORT_ORDER => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_SORT_ORDER => array(
                         array(1, null)
                     )
                 )
@@ -811,7 +810,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'secondary_invalid_store' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_secondary_invalid_store.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_STORE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_STORE => array(
                         array(1, null)
                     )
                 )
@@ -819,7 +818,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'secondary_incorrect_price' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_secondary_incorrect_price.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_ROW_PRICE => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_ROW_PRICE => array(
                         array(1, null)
                     )
                 )
@@ -827,7 +826,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'secondary_incorrect_row_sort' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_secondary_incorrect_row_sort.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_ROW_SORT => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_ROW_SORT => array(
                         array(1, null)
                     )
                 )
@@ -835,7 +834,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'secondary_row_sort_less_zero' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_secondary_row_sort_less_zero.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_INVALID_ROW_SORT => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_INVALID_ROW_SORT => array(
                         array(1, null)
                     )
                 )
@@ -854,7 +853,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'ambiguity_several_input_rows' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_main_valid.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_AMBIGUOUS_NEW_NAMES => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_AMBIGUOUS_NEW_NAMES => array(
                         array(1, null),
                         array(2, null)
                     )
@@ -865,7 +864,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'ambiguity_different_type' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_ambiguity_different_type.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_AMBIGUOUS_TYPES => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_AMBIGUOUS_TYPES => array(
                         array(1, null)
                     )
                 ),
@@ -874,7 +873,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
             'ambiguity_several_db_rows' => array(
                 '$rowData' => include __DIR__ . '/_files/row_data_ambiguity_several_db_rows.php',
                 '$errors' => array(
-                    \Magento\ImportExport\Model\Import\Entity\Product\Option::ERROR_AMBIGUOUS_OLD_NAMES => array(
+                    \Magento\CatalogImportExport\Model\Import\Product\Option::ERROR_AMBIGUOUS_OLD_NAMES => array(
                         array(1, null)
                     )
                 ),
@@ -901,7 +900,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
         $productModel->expects($this->any())->method('getProductEntitiesInfo')->will($this->returnValue(array()));
 
         $productEntity = $this->getMock(
-            '\Magento\ImportExport\Model\Import\Entity\Product',
+            '\Magento\CatalogImportExport\Model\Import\Product',
             array(),
             array(),
             '',
@@ -909,7 +908,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase
         );
 
         $model = $this->_helper->getObject(
-            'Magento\ImportExport\Model\Import\Entity\Product\Option',
+            'Magento\CatalogImportExport\Model\Import\Product\Option',
             array(
                 'data' => array(
                     'data_source_model' => $modelData,
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/product_with_custom_options.csv b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/product_with_custom_options.csv
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/product_with_custom_options.csv
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/product_with_custom_options.csv
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_ambiguity_different_type.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_ambiguity_different_type.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_ambiguity_several_db_rows.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_ambiguity_several_db_rows.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_empty_title.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_empty_title.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_empty_title.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_empty_title.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_incorrect_type.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_incorrect_type.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_incorrect_type.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_incorrect_type.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_max_characters.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_max_characters.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_max_characters.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_max_characters.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_price.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_price.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_price.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_price.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_sort_order.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_sort_order.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_sort_order.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_sort_order.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_store.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_store.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_invalid_store.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_invalid_store.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_max_characters_less_zero.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_max_characters_less_zero.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_max_characters_less_zero.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_max_characters_less_zero.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_no_title.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_no_title.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_no_title.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_no_title.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_sort_order_less_zero.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_sort_order_less_zero.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_sort_order_less_zero.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_sort_order_less_zero.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_valid.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_valid.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_main_valid.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_main_valid.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_no_custom_option.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_no_custom_option.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_no_custom_option.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_no_custom_option.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_incorrect_price.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_incorrect_price.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_incorrect_price.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_incorrect_price.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_incorrect_row_sort.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_incorrect_row_sort.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_incorrect_row_sort.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_incorrect_row_sort.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_invalid_store.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_invalid_store.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_invalid_store.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_invalid_store.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_row_sort_less_zero.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_row_sort_less_zero.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_row_sort_less_zero.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_row_sort_less_zero.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_valid.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_valid.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/Product/_files/row_data_secondary_valid.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/_files/row_data_secondary_valid.php
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
similarity index 90%
rename from dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index 8ebd20af7c3..9e0983a915b 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Entity/ProductTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Test class for \Magento\ImportExport\Model\Import\Entity\Product
+ * Test class for \Magento\CatalogImportExport\Model\Import\Product
  *
  * Magento
  *
@@ -23,7 +23,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\ImportExport\Model\Import\Entity;
+namespace Magento\CatalogImportExport\Model\Import;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -43,12 +43,12 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     protected $_eavConfig;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\OptionFactory|PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\CatalogImportExport\Model\Import\Product\OptionFactory|PHPUnit_Framework_MockObject_MockObject
      */
     protected $_optionFactory;
 
     /**
-     * @var \Magento\ImportExport\Model\Import\Entity\Product\Option|PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\CatalogImportExport\Model\Import\Product\Option|PHPUnit_Framework_MockObject_MockObject
      */
     protected $_optionModel;
 
@@ -123,14 +123,14 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $this->_eavConfig->expects($this->atLeastOnce())->method('getEntityTypeId')->will($this->returnValue('1'));
 
         $this->_optionModel = $this->getMock(
-            '\Magento\ImportExport\Model\Import\Entity\Product\Option',
+            '\Magento\CatalogImportExport\Model\Import\Product\Option',
             array(),
             array(),
             '',
             false
         );
         $this->_optionFactory = $this->getMock(
-            '\Magento\ImportExport\Model\Import\Entity\Product\OptionFactory',
+            '\Magento\CatalogImportExport\Model\Import\Product\OptionFactory',
             array('create'),
             array(),
             '',
@@ -189,7 +189,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
 
         $this->_importConfig = $this->getMock(
             '\Magento\ImportExport\Model\Import\Config',
-            array('getProductTypes'),
+            array('getEntityTypes'),
             array(),
             '',
             false
@@ -197,7 +197,9 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $this->_importConfig->expects(
             $this->atLeastOnce()
         )->method(
-            'getProductTypes'
+            'getEntityTypes'
+        )->with(
+            'catalog_product'
         )->will(
             $this->returnValue(array())
         );
@@ -278,7 +280,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
         $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
 
         $this->_model = $objectManager->getObject(
-            '\Magento\ImportExport\Model\Import\Entity\Product',
+            '\Magento\CatalogImportExport\Model\Import\Product',
             array(
                 'config' => $this->_eavConfig,
                 'optionFactory' => $this->_optionFactory,
@@ -304,20 +306,20 @@ class ProductTest extends \PHPUnit_Framework_TestCase
      */
     public function testIsMediaValid($data, $expected)
     {
-        $method = new \ReflectionMethod('\Magento\ImportExport\Model\Import\Entity\Product', '_isMediaValid');
+        $method = new \ReflectionMethod('\Magento\CatalogImportExport\Model\Import\Product', '_isMediaValid');
         $method->setAccessible(true);
 
         $this->assertEquals($expected['method_return'], $method->invoke($this->_model, $data, 1));
 
-        $errors = new \ReflectionProperty('\Magento\ImportExport\Model\Import\Entity\Product', '_errors');
+        $errors = new \ReflectionProperty('\Magento\CatalogImportExport\Model\Import\Product', '_errors');
         $errors->setAccessible(true);
         $this->assertEquals($expected['_errors'], $errors->getValue($this->_model));
 
-        $invalidRows = new \ReflectionProperty('\Magento\ImportExport\Model\Import\Entity\Product', '_invalidRows');
+        $invalidRows = new \ReflectionProperty('\Magento\CatalogImportExport\Model\Import\Product', '_invalidRows');
         $invalidRows->setAccessible(true);
         $this->assertEquals($expected['_invalidRows'], $invalidRows->getValue($this->_model));
 
-        $errorsCount = new \ReflectionProperty('\Magento\ImportExport\Model\Import\Entity\Product', '_errorsCount');
+        $errorsCount = new \ReflectionProperty('\Magento\CatalogImportExport\Model\Import\Product', '_errorsCount');
         $errorsCount->setAccessible(true);
         $this->assertEquals($expected['_errorsCount'], $errorsCount->getValue($this->_model));
     }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/ImportTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/ImportTest.php
similarity index 90%
rename from dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/ImportTest.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/ImportTest.php
index a5f256960ab..9db3f7d9da2 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/ImportTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/ImportTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Model\Indexer\Product\Flat\Plugin;
+namespace Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin;
 
 class ImportTest extends \PHPUnit_Framework_TestCase
 {
@@ -44,7 +44,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
 
         $someData = array(1, 2, 3);
 
-        $model = new \Magento\Catalog\Model\Indexer\Product\Flat\Plugin\Import($processorMock);
+        $model = new \Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin\Import($processorMock);
         $this->assertEquals($someData, $model->afterImportSource($subjectMock, $someData));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/ImportTest.php b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/ImportTest.php
similarity index 89%
rename from dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/ImportTest.php
rename to dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/ImportTest.php
index e8a3f62cbce..01cd873bcad 100644
--- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Indexer/Product/Price/Plugin/ImportTest.php
+++ b/dev/tests/unit/testsuite/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/ImportTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Catalog\Model\Indexer\Product\Price\Plugin;
+namespace Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin;
 
 class ImportTest extends \PHPUnit_Framework_TestCase
 {
@@ -31,7 +31,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
     protected $_objectManager;
 
     /**
-     * @var \Magento\Catalog\Model\Indexer\Product\Price\Plugin\Import
+     * @var \Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin\Import
      */
     protected $_model;
 
@@ -54,7 +54,7 @@ class ImportTest extends \PHPUnit_Framework_TestCase
         $this->_indexerMock->expects($this->any())->method('getId')->will($this->returnValue(1));
 
         $this->_model = $this->_objectManager->getObject(
-            'Magento\Catalog\Model\Indexer\Product\Price\Plugin\Import',
+            'Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin\Import',
             array('indexer' => $this->_indexerMock)
         );
     }
diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Controller/AdvancedTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Controller/AdvancedTest.php
new file mode 100644
index 00000000000..32229adf238
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Controller/AdvancedTest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Controller;
+
+class AdvancedTest extends \PHPUnit_Framework_TestCase
+{
+    public function testResultActionFiltersSetBeforeLoadLayout()
+    {
+        $filters = null;
+        $expectedQuery = 'filtersData';
+
+        $view = $this->getMock('Magento\Framework\App\View', array('loadLayout', 'renderLayout'), array(), '', false);
+        $view->expects($this->once())->method('loadLayout')->will(
+            $this->returnCallback(
+                function () use (&$filters, $expectedQuery) {
+                    $this->assertEquals($expectedQuery, $filters);
+                }
+            )
+        );
+
+        $request = $this->getMock('Magento\Framework\App\Console\Request', array('getQuery'), array(), '', false);
+        $request->expects($this->once())->method('getQuery')->will($this->returnValue($expectedQuery));
+
+        $catalogSearchAdvanced = $this->getMock(
+            'Magento\CatalogSearch\Model\Advanced',
+            array('addFilters', '__wakeup'),
+            array(),
+            '',
+            false
+        );
+        $catalogSearchAdvanced->expects($this->once())->method('addFilters')->will(
+            $this->returnCallback(
+                function ($added) use (&$filters) {
+                    $filters = $added;
+                }
+            )
+        );
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $context = $objectManager->getObject(
+            'Magento\Framework\App\Action\Context',
+            array('view' => $view, 'request' => $request)
+        );
+
+        /** @var \Magento\CatalogSearch\Controller\Advanced $instance */
+        $instance = $objectManager->getObject(
+            'Magento\CatalogSearch\Controller\Advanced',
+            array('context' => $context, 'catalogSearchAdvanced' => $catalogSearchAdvanced)
+        );
+        $instance->resultAction();
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php
new file mode 100644
index 00000000000..c8f9d6a654f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\CatalogSearch\Model;
+
+class AdvancedTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product\Attribute\Backend\Sku
+     */
+    protected $skuAttribute;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\Advanced\Collection
+     */
+    protected $collection;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\Advanced
+     */
+    protected $resource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\Fulltext\Engine
+     */
+    protected $engine;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\EngineProvider
+     */
+    protected $engineProvider;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Resource\Eav\Attribute
+     */
+    protected $attribute;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Data\Collection
+     */
+    protected $dataCollection;
+
+    protected function setUp()
+    {
+        $this->skuAttribute = $this->getMock(
+            'Magento\Catalog\Model\Product\Attribute\Backend\Sku',
+            array('getTable'),
+            array(),
+            '',
+            false
+        );
+        $this->collection = $this->getMock(
+            'Magento\CatalogSearch\Model\Resource\Advanced\Collection',
+            array(
+                'addAttributeToSelect',
+                'setStore',
+                'addMinimalPrice',
+                'addTaxPercents',
+                'addStoreFilter',
+                'setVisibility',
+                'addFieldsToFilter'
+            ),
+            array(),
+            '',
+            false
+        );
+        $this->resource = $this->getMock(
+            'Magento\CatalogSearch\Model\Resource\Advanced',
+            array('prepareCondition', '__wakeup', 'getIdFieldName'),
+            array(),
+            '',
+            false
+        );
+        $this->engine = $this->getMock(
+            'Magento\CatalogSearch\Model\Resource\Fulltext\Engine',
+            array('getResource', '__wakeup', 'getAdvancedResultCollection'),
+            array(),
+            '',
+            false
+        );
+        $this->engineProvider = $this->getMock(
+            'Magento\CatalogSearch\Model\Resource\EngineProvider',
+            array('get'),
+            array(),
+            '',
+            false
+        );
+        $this->attribute = $this->getMock(
+            'Magento\Catalog\Model\Resource\Eav\Attribute',
+            array('getAttributeCode', 'getStoreLabel', 'getFrontendInput', 'getBackend', 'getBackendType', '__wakeup'),
+            array(),
+            '',
+            false
+        );
+        $this->dataCollection = $this->getMock(
+            'Magento\Framework\Data\Collection',
+            array('getIterator'),
+            array(),
+            '',
+            false
+        );
+    }
+
+    public function testAddFiltersVerifyAddConditionsToRegistry()
+    {
+        $registry = new \Magento\Framework\Registry();
+        $values = array('sku' => 'simple');
+        $this->skuAttribute->expects($this->once())->method('getTable')
+            ->will($this->returnValue('catalog_product_entity'));
+        $this->collection->expects($this->any())->method('addAttributeToSelect')->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('setStore')->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('addMinimalPrice')->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('addTaxPercents')->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('addStoreFilter')->will($this->returnSelf());
+        $this->collection->expects($this->any())->method('setVisibility')->will($this->returnSelf());
+        $this->resource->expects($this->any())->method('prepareCondition')
+            ->will($this->returnValue(array('like' => '%simple%')));
+        $this->resource->expects($this->any())->method('getIdFieldName')->will($this->returnValue('entity_id'));
+        $this->engine->expects($this->any())->method('getResource')->will($this->returnValue($this->resource));
+        $this->engine->expects($this->any())->method('getAdvancedResultCollection')
+            ->will($this->returnValue($this->collection));
+        $this->engineProvider->expects($this->any())->method('get')->will($this->returnValue($this->engine));
+        $this->attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue('sku'));
+        $this->attribute->expects($this->any())->method('getStoreLabel')->will($this->returnValue('SKU'));
+        $this->attribute->expects($this->any())->method('getFrontendInput')->will($this->returnValue('text'));
+        $this->attribute->expects($this->any())->method('getBackend')->will($this->returnValue($this->skuAttribute));
+        $this->attribute->expects($this->any())->method('getBackendType')->will($this->returnValue('static'));
+        $this->dataCollection->expects($this->any())->method('getIterator')
+            ->will($this->returnValue(new \ArrayIterator(array($this->attribute))));
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        /** @var \Magento\CatalogSearch\Model\Advanced $instance */
+        $instance = $objectManager->getObject(
+            'Magento\CatalogSearch\Model\Advanced',
+            array(
+                'registry' => $registry,
+                'engineProvider' => $this->engineProvider,
+                'data' => array('attributes' => $this->dataCollection)
+            )
+        );
+        $instance->addFilters($values);
+        $this->assertNotNull($registry->registry('advanced_search_conditions'));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Export/RowCustomizerTest.php b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Export/RowCustomizerTest.php
index 4fb88f49ccf..87b43a19e22 100644
--- a/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Export/RowCustomizerTest.php
+++ b/dev/tests/unit/testsuite/Magento/ConfigurableProduct/Model/Export/RowCustomizerTest.php
@@ -26,7 +26,7 @@ namespace Magento\ConfigurableProduct\Model\Export;
 class RowCustomizerTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\ConfigurableProduct\Model\Export\RowCustomizer
+     * @var \Magento\CatalogImportExport\Model\Export\RowCustomizer
      */
     protected $_model;
 
@@ -44,7 +44,7 @@ class RowCustomizerTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->_model = new \Magento\ConfigurableProduct\Model\Export\RowCustomizer;
+        $this->_model = new \Magento\CatalogImportExport\Model\Export\RowCustomizer;
     }
 
     public function testPrepareData()
diff --git a/dev/tests/unit/testsuite/Magento/Core/Model/Theme/ValidationTest.php b/dev/tests/unit/testsuite/Magento/Core/Model/Theme/ValidationTest.php
index b497394110c..45acb282abf 100644
--- a/dev/tests/unit/testsuite/Magento/Core/Model/Theme/ValidationTest.php
+++ b/dev/tests/unit/testsuite/Magento/Core/Model/Theme/ValidationTest.php
@@ -56,7 +56,7 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
                 array(
                     'theme_code' => 'Magento/iphone',
                     'theme_title' => 'Iphone',
-                    'theme_version' => '2.0.0.0',
+                    'theme_version' => '2.0.0',
                     'parent_theme' => array('default', 'default'),
                     'theme_path' => 'Magento/iphone',
                     'preview_image' => 'images/preview.png'
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Helper/AddressTest.php b/dev/tests/unit/testsuite/Magento/Customer/Helper/AddressTest.php
index bd0a2419d3d..e86aa48ba70 100755
--- a/dev/tests/unit/testsuite/Magento/Customer/Helper/AddressTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Helper/AddressTest.php
@@ -67,17 +67,13 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             'Magento\Customer\Model\Address\Config'
         )->disableOriginalConstructor()->getMock();
 
-        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->helper = $objectManager->getObject(
-            'Magento\Customer\Helper\Address',
-            array(
-                'context' => $this->context,
-                'blockFactory' => $this->blockFactory,
-                'storeManager' => $this->storeManager,
-                'scopeConfig' => $this->scopeConfig,
-                'customerMetadataService' => $this->customerMetadataService,
-                'addressConfig' => $this->addressConfig
-            )
+        $this->helper = new \Magento\Customer\Helper\Address(
+            $this->context,
+            $this->blockFactory,
+            $this->storeManager,
+            $this->scopeConfig,
+            $this->customerMetadataService,
+            $this->addressConfig
         );
     }
 
@@ -120,4 +116,288 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             array(10, 4)
         );
     }
+
+    /**
+     * @dataProvider getRendererDataProvider
+     */
+    public function testGetRenderer($renderer, $blockFactory, $result)
+    {
+        $this->helper = new \Magento\Customer\Helper\Address(
+            $this->context,
+            $blockFactory,
+            $this->storeManager,
+            $this->scopeConfig,
+            $this->customerMetadataService,
+            $this->addressConfig
+        );
+        $this->assertEquals($result, $this->helper->getRenderer($renderer));
+    }
+
+    /**
+     * @return array
+     */
+    public function getRendererDataProvider()
+    {
+        $blockMock = $this->getMockBuilder('Magento\Framework\View\Element\BlockInterface')->getMock();
+        $blockFactory = $this->getMockBuilder(
+            'Magento\Framework\View\Element\BlockFactory'
+        )->disableOriginalConstructor()->getMock();
+        $blockFactory->expects($this->once())
+            ->method('createBlock')
+            ->with('some_test_block', array())
+            ->will($this->returnValue($blockMock));
+        return array(
+            array('some_test_block', $blockFactory, $blockMock),
+            array($blockMock, $blockFactory, $blockMock),
+        );
+    }
+
+    public function testGetConfigCanShowConfig()
+    {
+        $result = array('key1' => 'value1', 'key2' => 'value2');
+        $store = $this->getMockBuilder('Magento\Store\Model\Store')->disableOriginalConstructor()->getMock();
+        $store->expects($this->any())
+            ->method('getWebsiteId')
+            ->will($this->returnValue('1'));
+        $this->scopeConfig->expects($this->once())//test method cache
+            ->method('getValue')
+            ->with('customer/address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store)
+            ->will($this->returnValue($result));
+        $this->storeManager->expects($this->any())->method('getStore')->will($this->returnValue($store));
+        $this->assertNull($this->helper->getConfig('unavailable_key'));
+        $this->assertFalse($this->helper->canShowConfig('unavailable_key'));
+        $this->assertEquals($result['key1'], $this->helper->getConfig('key1'));
+        $this->assertEquals($result['key2'], $this->helper->getConfig('key2'));
+        $this->assertTrue($this->helper->canShowConfig('key1'));
+        $this->assertTrue($this->helper->canShowConfig('key2'));
+    }
+
+    /**
+     * @param $attrCode
+     * @param $attrClass
+     * @param $customAttrClass
+     * @param $result
+     * @dataProvider getAttributeValidationClassDataProvider
+     */
+    public function testGetAttributeValidationClass($attrCode, $attrClass, $customAttrClass, $result)
+    {
+        $attributeMock = $this->getMockBuilder('Magento\Customer\Service\V1\Data\Eav\AttributeMetadata')
+            ->disableOriginalConstructor()->getMock();
+        $attributeMock->expects($this->any())->method('getFrontendClass')->will($this->returnValue($attrClass));
+
+        $customAttrMock = $this->getMockBuilder('Magento\Customer\Service\V1\Data\Eav\AttributeMetadata')
+            ->disableOriginalConstructor()->getMock();
+        $customAttrMock->expects($this->any())->method('isVisible')->will($this->returnValue(true));
+        $customAttrMock->expects($this->any())->method('getFrontendClass')->will($this->returnValue($customAttrClass));
+
+        $this->customerMetadataService->expects($this->any())
+            ->method('getAttributeMetadata')
+            ->will($this->returnValueMap(
+                array(
+                    array('customer_address', $attrCode, $attributeMock),
+                    array('customer', $attrCode, $customAttrMock),
+                )
+            ));
+
+        $this->assertEquals($result, $this->helper->getAttributeValidationClass($attrCode));
+    }
+
+    public function getAttributeValidationClassDataProvider()
+    {
+        return array(
+            array('attr_code', 'Attribute_Class', '', 'Attribute_Class'),
+            array('firstname', 'Attribute_Class', 'Attribute2_Class', 'Attribute2_Class'),
+        );
+    }
+
+    /**
+     * @param $origStreets
+     * @param $toCount
+     * @param $result
+     * @dataProvider getConvertStreetLinesDataProvider
+     */
+    public function testConvertStreetLines($origStreets, $toCount, $result)
+    {
+        $this->assertEquals($result, $this->helper->convertStreetLines($origStreets, $toCount));
+    }
+
+    public function getConvertStreetLinesDataProvider()
+    {
+        return array(
+            array(array('street1', 'street2', 'street3', 'street4'), 3, array('street1 street2', 'street3', 'street4')),
+            array(array('street1', 'street2', 'street3', 'street4'), 2, array('street1 street2', 'street3 street4')),
+        );
+    }
+
+    /**
+     * @param $store
+     * @param $result
+     * @dataProvider getVatValidationEnabledDataProvider
+     */
+    public function testIsVatValidationEnabled($store, $result)
+    {
+        $this->scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with(
+                \Magento\Customer\Helper\Address::XML_PATH_VAT_VALIDATION_ENABLED,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                $store
+            )
+            ->will($this->returnValue($result));
+        $this->assertEquals($result, $this->helper->isVatValidationEnabled($store));
+    }
+
+    /**
+     * @return array
+     */
+    public function getVatValidationEnabledDataProvider()
+    {
+        return array(
+            array(0, true),
+            array(1, false),
+            array(2, true),
+        );
+    }
+
+    /**
+     * @param $store
+     * @param $result
+     * @dataProvider getValidateOnEachTransactionDataProvider
+     */
+    public function testHasValidateOnEachTransaction($store, $result)
+    {
+        $this->scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with(
+                \Magento\Customer\Helper\Address::XML_PATH_VIV_ON_EACH_TRANSACTION,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                $store
+            )
+            ->will($this->returnValue($result));
+        $this->assertEquals($result, $this->helper->hasValidateOnEachTransaction($store));
+    }
+
+    /**
+     * @return array
+     */
+    public function getValidateOnEachTransactionDataProvider()
+    {
+        return array(
+            array(0, true),
+            array(1, false),
+            array(2, true),
+        );
+    }
+
+    /**
+     * @param $store
+     * @param $result
+     * @dataProvider getTaxCalculationAddressTypeDataProvider
+     */
+    public function testGetTaxCalculationAddressType($store, $result)
+    {
+        $this->scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with(
+                \Magento\Customer\Helper\Address::XML_PATH_VIV_TAX_CALCULATION_ADDRESS_TYPE,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                $store
+            )
+            ->will($this->returnValue($result));
+        $this->assertEquals($result, $this->helper->getTaxCalculationAddressType($store));
+    }
+
+    /**
+     * @return array
+     */
+    public function getTaxCalculationAddressTypeDataProvider()
+    {
+        return array(
+            array(0, 'address_type_store_0'),
+            array(1, 'address_type_store_1'),
+            array(2, 'address_type_store_2'),
+        );
+    }
+
+    public function testIsDisableAutoGroupAssignDefaultValue()
+    {
+        $this->scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with(
+                \Magento\Customer\Helper\Address::XML_PATH_VIV_DISABLE_AUTO_ASSIGN_DEFAULT,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            )
+            ->will($this->returnValue(true));
+        $this->assertTrue($this->helper->isDisableAutoGroupAssignDefaultValue());
+    }
+
+    public function testIsVatAttributeVisible()
+    {
+        $this->scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with(
+                \Magento\Customer\Helper\Address::XML_PATH_VAT_FRONTEND_VISIBILITY,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            )
+            ->will($this->returnValue(true));
+        $this->assertTrue($this->helper->isVatAttributeVisible());
+    }
+
+    /**
+     * @param string $code
+     * @param \Magento\Customer\Block\Address\Renderer\RendererInterface|null $result
+     * @dataProvider getFormatTypeRendererDataProvider
+     */
+    public function testGetFormatTypeRenderer($code, $result)
+    {
+        $this->addressConfig->expects($this->once())
+            ->method('getFormatByCode')
+            ->with($code)
+            ->will($this->returnValue(
+                new \Magento\Framework\Object(!is_null($result)?array('renderer' => $result):array())
+            ));
+        $this->assertEquals($result, $this->helper->getFormatTypeRenderer($code));
+    }
+
+    public function getFormatTypeRendererDataProvider()
+    {
+        $renderer = $this->getMockBuilder('Magento\Customer\Block\Address\Renderer\RendererInterface')
+            ->disableOriginalConstructor()->getMock();
+        return array(
+            array('valid_code', $renderer),
+            array('invalid_code', null)
+        );
+    }
+
+    /**
+     * @param string $code
+     * @param array $result
+     * @dataProvider getFormatDataProvider
+     */
+    public function testGetFormat($code, $result)
+    {
+        if ($result) {
+            $renderer = $this->getMockBuilder('Magento\Customer\Block\Address\Renderer\RendererInterface')
+                ->disableOriginalConstructor()->getMock();
+            $renderer->expects($this->once())
+                ->method('getFormatArray')
+                ->will($this->returnValue(array('key' => 'value')));
+        }
+        $this->addressConfig->expects($this->once())
+            ->method('getFormatByCode')
+            ->with($code)
+            ->will($this->returnValue(
+                new \Magento\Framework\Object(!empty($result)?array('renderer' => $renderer):array())
+            ));
+
+        $this->assertEquals($result, $this->helper->getFormat($code));
+    }
+
+    public function getFormatDataProvider()
+    {
+        return array(
+            array('valid_code', array('key' => 'value')),
+            array('invalid_code', '')
+        );
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Helper/ViewTest.php b/dev/tests/unit/testsuite/Magento/Customer/Helper/ViewTest.php
new file mode 100644
index 00000000000..be6e7179982
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Helper/ViewTest.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Customer\Helper;
+
+class ViewTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\App\Helper\Context|\PHPUnit_Framework_MockObject_MockObject */
+    protected $context;
+
+    /** @var \Magento\Customer\Helper\View|\PHPUnit_Framework_MockObject_MockObject */
+    protected $object;
+
+    /** @var \Magento\Customer\Service\V1\CustomerMetadataServiceInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerMetadataService;
+
+    public function setUp()
+    {
+        $this->context = $this->getMockBuilder('Magento\Framework\App\Helper\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customerMetadataService = $this->getMockBuilder(
+            'Magento\Customer\Service\V1\CustomerMetadataServiceInterface'
+        )->disableOriginalConstructor()->getMock();
+
+        $attributeMetadata = $this->getMockBuilder('Magento\Customer\Service\V1\Data\Eav\AttributeMetadata')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $attributeMetadata->expects($this->any())->method('isVisible')->will($this->returnValue(true));
+        $this->customerMetadataService->expects($this->any())
+            ->method('getAttributeMetadata')
+            ->will($this->returnValue($attributeMetadata));
+
+        $this->object = new View($this->context, $this->customerMetadataService);
+    }
+
+    /**
+     * @dataProvider getCustomerServiceDataProvider
+     */
+    public function testGetCustomerName($prefix, $firstName, $middleName, $lastName, $suffix, $result)
+    {
+        $customerData = $this->getMockBuilder('Magento\Customer\Service\V1\Data\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $customerData->expects($this->any())
+            ->method('getPrefix')->will($this->returnValue($prefix));
+        $customerData->expects($this->any())
+            ->method('getFirstname')->will($this->returnValue($firstName));
+        $customerData->expects($this->any())
+            ->method('getMiddlename')->will($this->returnValue($middleName));
+        $customerData->expects($this->any())
+            ->method('getLastname')->will($this->returnValue($lastName));
+        $customerData->expects($this->any())
+            ->method('getSuffix')->will($this->returnValue($suffix));
+        $this->assertEquals($result, $this->object->getCustomerName($customerData));
+    }
+
+    /**
+     * @return array
+     */
+    public function getCustomerServiceDataProvider()
+    {
+        return array(
+            array(
+                'prefix', //prefix
+                'first_name', //first_name
+                'middle_name', //middle_name
+                'last_name', //last_name
+                'suffix', //suffix
+                'prefix first_name middle_name last_name suffix', //result name
+            ),
+            array(
+                '', //prefix
+                'first_name', //first_name
+                'middle_name', //middle_name
+                'last_name', //last_name
+                'suffix', //suffix
+                'first_name middle_name last_name suffix', //result name
+            ),
+            array(
+                'prefix', //prefix
+                'first_name', //first_name
+                '', //middle_name
+                'last_name', //last_name
+                'suffix', //suffix
+                'prefix first_name last_name suffix', //result name
+            ),
+            array(
+                'prefix', //prefix
+                'first_name', //first_name
+                'middle_name', //middle_name
+                'last_name', //last_name
+                '', //suffix
+                'prefix first_name middle_name last_name', //result name
+            ),
+            array(
+                '', //prefix
+                'first_name', //first_name
+                '', //middle_name
+                'last_name', //last_name
+                'suffix', //suffix
+                'first_name last_name suffix', //result name
+            ),
+            array(
+                'prefix', //prefix
+                'first_name', //first_name
+                '', //middle_name
+                'last_name', //last_name
+                '', //suffix
+                'prefix first_name last_name', //result name
+            ),
+            array(
+                '', //prefix
+                'first_name', //first_name
+                'middle_name', //middle_name
+                'last_name', //last_name
+                '', //suffix
+                'first_name middle_name last_name', //result name
+            ),
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Address/AbstractAddressTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Address/AbstractAddressTest.php
new file mode 100644
index 00000000000..499362a7e7e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Address/AbstractAddressTest.php
@@ -0,0 +1,328 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *   
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model\Address;
+
+class AbstractAddressTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $contextMock;
+
+    /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $registryMock;
+
+    /** @var \Magento\Directory\Helper\Data|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $directoryDataMock;
+
+    /** @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $eavConfigMock;
+
+    /** @var \Magento\Customer\Model\Address\Config|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $addressConfigMock;
+
+    /** @var \Magento\Directory\Model\RegionFactory|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $regionFactoryMock;
+
+    /** @var \Magento\Directory\Model\CountryFactory|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $countryFactoryMock;
+
+    /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $resourceMock;
+
+    /** @var \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $resourceCollectionMock;
+
+    /** @var \Magento\Customer\Model\Address\AbstractAddress  */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->contextMock = $this->getMock('Magento\Framework\Model\Context', array(), array(), '', false);
+        $this->registryMock = $this->getMock('Magento\Framework\Registry', array(), array(), '', false);
+        $this->directoryDataMock = $this->getMock('Magento\Directory\Helper\Data', array(), array(), '', false);
+        $this->eavConfigMock = $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false);
+        $this->addressConfigMock = $this->getMock('Magento\Customer\Model\Address\Config', array(), array(), '', false);
+        $this->regionFactoryMock = $this->getMock(
+            'Magento\Directory\Model\RegionFactory',
+            array('create'),
+            array(),
+            '',
+            false
+        );
+        $this->countryFactoryMock = $this->getMock(
+            'Magento\Directory\Model\CountryFactory',
+            array('create'),
+            array(),
+            '',
+            false
+        );
+        $regionCollectionMock = $this->getMock(
+            'Magento\Directory\Model\Resource\Region\Collection',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $regionCollectionMock->expects($this->any())
+            ->method('getSize')
+            ->will($this->returnValue(0));
+        $countryMock = $this->getMock('Magento\Directory\Model\Country', array(), array(), '', false);
+        $countryMock->expects($this->any())
+            ->method('getRegionCollection')
+            ->will($this->returnValue($regionCollectionMock));
+        $this->countryFactoryMock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($countryMock));
+
+        $this->resourceMock = $this->getMock('Magento\Customer\Model\Resource\Customer', array(), array(), '', false);
+        $this->resourceCollectionMock = $this->getMock(
+            'Magento\Framework\Data\Collection\Db',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $this->model = $this->getMockForAbstractClass(
+            'Magento\Customer\Model\Address\AbstractAddress',
+            array(
+                'context' => $this->contextMock,
+                'registry' => $this->registryMock,
+                'directoryData' => $this->directoryDataMock,
+                'eavConfig' => $this->eavConfigMock,
+                'addressConfig' => $this->addressConfigMock,
+                'regionFactory' => $this->regionFactoryMock,
+                'countryFactory' => $this->countryFactoryMock,
+                'resource' => $this->resourceMock,
+                'resourceCollection' => $this->resourceCollectionMock,
+            ),
+            '',
+            true,
+            false
+
+        );
+    }
+
+    public function testGetRegionWithRegionId()
+    {
+        $countryId = 1;
+        $this->prepareGetRegion($countryId);
+
+        $this->model->setData(array(
+                'region_id' => 1,
+                'region' => '',
+                'country_id' => $countryId,
+            ));
+        $this->assertEquals('RegionName', $this->model->getRegion());
+    }
+
+    public function testGetRegionWithRegion()
+    {
+        $countryId = 2;
+        $this->prepareGetRegion($countryId);
+
+        $this->model->setData(array(
+                'region_id' => '',
+                'region' => 2,
+                'country_id' => $countryId,
+            ));
+        $this->assertEquals('RegionName', $this->model->getRegion());
+    }
+
+    public function testGetRegionWithRegionName()
+    {
+        $this->regionFactoryMock->expects($this->never())->method('create');
+
+        $this->model->setData(array(
+                'region_id' => '',
+                'region' => 'RegionName',
+            ));
+        $this->assertEquals('RegionName', $this->model->getRegion());
+    }
+
+    public function testGetRegionWithoutRegion()
+    {
+        $this->regionFactoryMock->expects($this->never())->method('create');
+
+        $this->assertNull($this->model->getRegion());
+    }
+
+    public function testGetRegionCodeWithRegionId()
+    {
+        $countryId = 1;
+        $this->prepareGetRegionCode($countryId);
+
+        $this->model->setData(array(
+                'region_id' => 3,
+                'region' => '',
+                'country_id' => $countryId,
+            ));
+        $this->assertEquals('UK', $this->model->getRegionCode());
+    }
+
+    public function testGetRegionCodeWithRegion()
+    {
+        $countryId = 2;
+        $this->prepareGetRegionCode($countryId);
+
+        $this->model->setData(array(
+                'region_id' => '',
+                'region' => 4,
+                'country_id' => $countryId,
+            ));
+        $this->assertEquals('UK', $this->model->getRegionCode());
+    }
+
+    public function testGetRegionCodeWithRegionName()
+    {
+        $this->regionFactoryMock->expects($this->never())->method('create');
+
+        $this->model->setData(array(
+                'region_id' => '',
+                'region' => 'UK',
+            ));
+        $this->assertEquals('UK', $this->model->getRegionCode());
+    }
+
+    public function testGetRegionCodeWithoutRegion()
+    {
+        $this->regionFactoryMock->expects($this->never())->method('create');
+
+        $this->assertNull($this->model->getRegionCode());
+    }
+
+    /**
+     * @param $countryId
+     */
+    protected function prepareGetRegion($countryId, $regionName = 'RegionName')
+    {
+        $region = $this->getMock(
+            'Magento\Directory\Model\Region',
+            array('getCountryId', 'getName', '__wakeup', 'load'),
+            array(),
+            '',
+            false
+        );
+        $region->expects($this->once())
+            ->method('getName')
+            ->will($this->returnValue($regionName));
+        $region->expects($this->once())
+            ->method('getCountryId')
+            ->will($this->returnValue($countryId));
+        $this->regionFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($region));
+    }
+
+    /**
+     * @param $countryId
+     */
+    protected function prepareGetRegionCode($countryId, $regionCode = 'UK')
+    {
+        $region = $this->getMock(
+            'Magento\Directory\Model\Region',
+            array('getCountryId', 'getCode', '__wakeup', 'load'),
+            array(),
+            '',
+            false
+        );
+        $region->expects($this->once())
+            ->method('getCode')
+            ->will($this->returnValue($regionCode));
+        $region->expects($this->once())
+            ->method('getCountryId')
+            ->will($this->returnValue($countryId));
+        $this->regionFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($region));
+    }
+
+    /**
+     * @param $data
+     * @param $expected
+     *
+     * @dataProvider validateDataProvider
+     */
+    public function testValidate($data, $expected)
+    {
+        $this->directoryDataMock->expects($this->once())
+            ->method('getCountriesWithOptionalZip')
+            ->will($this->returnValue(array()));
+
+        $this->directoryDataMock->expects($this->never())
+            ->method('isRegionRequired');
+
+        $this->model->setData($data);
+
+        $this->assertEquals($expected, $this->model->validate());
+    }
+
+    /**
+     * @return array
+     */
+    public function validateDataProvider()
+    {
+        $countryId = 1;
+        $data = array(
+            'firstname' => 'First Name',
+            'lastname' => 'Last Name',
+            'street' => "Street 1\nStreet 2",
+            'city' => 'Odessa',
+            'telephone' => '555-55-55',
+            'country_id' => $countryId,
+            'postcode' => 07201,
+            'region_id' => 1,
+        );
+        return array(
+            'firstname' =>array(
+                array_merge(array_diff_key($data, array('firstname' => '')), array('country_id' => $countryId++)),
+                array('Please enter the first name.')
+            ),
+            'lastname' => array(
+                array_merge(array_diff_key($data, array('lastname' => '')), array('country_id' => $countryId++)),
+                array('Please enter the last name.')
+            ),
+            'street' => array(
+                array_merge(array_diff_key($data, array('street' => '')), array('country_id' => $countryId++)),
+                array('Please enter the street.')
+            ),
+            'city' => array(
+                array_merge(array_diff_key($data, array('city' => '')), array('country_id' => $countryId++)),
+                array('Please enter the city.')
+            ),
+            'telephone' => array(
+                array_merge(array_diff_key($data, array('telephone' => '')), array('country_id' => $countryId++)),
+                array('Please enter the telephone number.')
+            ),
+            'postcode' => array(
+                array_merge(array_diff_key($data, array('postcode' => '')), array('country_id' => $countryId++)),
+                array('Please enter the zip/postal code.')
+            ),
+            'country_id' => array(
+                array_diff_key($data, array('country_id' => '')),
+                array('Please enter the country.')
+            ),
+            'validated' => array(array_merge($data, array('country_id' => $countryId++)), true),
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Address/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Address/ConverterTest.php
new file mode 100644
index 00000000000..3808e8c3bb0
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Address/ConverterTest.php
@@ -0,0 +1,297 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *   
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Customer\Model\Address;
+
+use Magento\Framework\Service\Data\Eav\AttributeValue;
+
+class ConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Converter
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Customer\Service\V1\Data\AddressBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $addressBuilderMock;
+
+    /**
+     * @var \Magento\Customer\Model\AddressFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $addressFactoryMock;
+
+    /**
+     * @var \Magento\Customer\Service\V1\Data\RegionBuilder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $regionBuilderMock;
+
+    /**
+     *
+     * @var \Magento\Customer\Service\V1\CustomerMetadataServiceInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $metadataServiceMock;
+
+    protected function setUp()
+    {
+        $this->addressBuilderMock = $this->getMock(
+            'Magento\Customer\Service\V1\Data\AddressBuilder',
+            array('populateWithArray', 'setId', 'setCustomerId', 'create'),
+            array(),
+            '',
+            false
+        );
+
+        $this->addressFactoryMock = $this->getMock(
+            'Magento\Customer\Model\AddressFactory',
+            array('create'),
+            array(),
+            '',
+            false
+        );
+
+        $this->regionBuilderMock = $this->getMock(
+            'Magento\Customer\Service\V1\Data\RegionBuilder',
+            array(),
+            array(),
+            '',
+            false
+        );
+
+        $this->metadataServiceMock = $this->getMock(
+            'Magento\Customer\Service\V1\CustomerMetadataService',
+            array('getAllAddressAttributeMetadata'),
+            array(),
+            '',
+            false
+        );
+
+        $this->model = new Converter(
+            $this->addressBuilderMock,
+            $this->addressFactoryMock,
+            $this->metadataServiceMock
+        );
+    }
+
+    public function testUpdateAddressModel()
+    {
+        $addressModelMock = $this->getAddressModelMock();
+        $addressModelMock->expects($this->once())
+            ->method('getAttributeSetId')
+            ->will($this->returnValue(false));
+        $addressModelMock->expects($this->once())
+            ->method('setAttributeSetId')
+            ->with($this->equalTo(
+                \Magento\Customer\Service\V1\CustomerMetadataServiceInterface::ATTRIBUTE_SET_ID_ADDRESS
+            ));
+
+        $addressMock = $this->getMock('Magento\Customer\Service\V1\Data\Address', array(), array(), '', false);
+        $addressMock->expects($this->once())
+            ->method('__toArray')
+            ->will($this->returnValue(array()));
+
+        $this->model->updateAddressModel($addressModelMock, $addressMock);
+    }
+
+    public function testUpdateAddressModelWithAttributes()
+    {
+        $addressModelMock = $this->getAddressModelMock();
+        $addressModelMock->expects($this->once())
+            ->method('getAttributeSetId')
+            ->will($this->returnValue(true));
+        $addressModelMock->expects($this->never())
+            ->method('setAttributeSetId');
+
+        $attributes = array(
+            'custom_attributes' => array(
+                array(AttributeValue::ATTRIBUTE_CODE => 'code_01', AttributeValue::VALUE => 'value_01'),
+                array(AttributeValue::ATTRIBUTE_CODE => 'code_02', AttributeValue::VALUE => 'value_02'),
+                array(AttributeValue::ATTRIBUTE_CODE => 'code_03', AttributeValue::VALUE => 'value_03'),
+            ),
+            'attributes_01' => array('some_value_01', 'some_value_02', 'some_value_03'),
+            'attributes_02' => 'some_value_04',
+            \Magento\Customer\Service\V1\Data\Address::KEY_REGION => 'some_region',
+        );
+        $regionMock = $this->getMock(
+            'Magento\Customer\Service\V1\Data\Region',
+            array('getRegion', 'getRegionCode', 'getRegionId'),
+            array(),
+            '',
+            false
+        );
+        $regionMock->expects($this->once())->method('getRegion');
+        $regionMock->expects($this->once())->method('getRegionCode');
+        $regionMock->expects($this->once())->method('getRegionId');
+        $addressMock = $this->getMock('Magento\Customer\Service\V1\Data\Address', array(), array(), '', false);
+        $addressMock->expects($this->once())
+            ->method('__toArray')
+            ->will($this->returnValue($attributes));
+        $addressMock->expects($this->exactly(4))
+            ->method('getRegion')
+            ->will($this->returnValue($regionMock));
+
+        $this->model->updateAddressModel($addressModelMock, $addressMock);
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getAddressModelMock()
+    {
+        $addressModelMock = $this->getMock(
+            'Magento\Customer\Model\Address',
+            array('setIsDefaultBilling', 'setIsDefaultShipping', 'setAttributeSetId', 'getAttributeSetId', '__wakeup'),
+            array(),
+            '',
+            false
+        );
+        $addressModelMock->expects($this->once())
+            ->method('setIsDefaultBilling');
+        $addressModelMock->expects($this->once())
+            ->method('setIsDefaultShipping');
+        return $addressModelMock;
+    }
+
+    public function testCreateAddressFromModel()
+    {
+        $defaultBillingId = 1;
+        $defaultShippingId = 1;
+        $addressId = 1;
+
+        $addressModelMock = $this->getAddressMockForCreate();
+        $addressModelMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($addressId));
+        $addressModelMock->expects($this->any())
+            ->method('getCustomerId');
+        $addressModelMock->expects($this->any())
+            ->method('getParentId');
+
+        $addressMock = $this->getMock('Magento\Customer\Service\V1\Data\Address', array(), array(), '', false);
+        $this->metadataServiceMock->expects($this->once())
+            ->method('getAllAddressAttributeMetadata')
+            ->will($this->returnValue(array()));
+        $this->addressBuilderMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($addressMock));
+        $this->addressBuilderMock->expects($this->once())
+            ->method('setId')
+            ->with($this->equalTo($addressId));
+        $this->addressBuilderMock->expects($this->never())
+            ->method('setCustomerId');
+        $this->assertEquals(
+            $addressMock,
+            $this->model->createAddressFromModel($addressModelMock, $defaultBillingId, $defaultShippingId)
+        );
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
+     */
+    public function testCreateAddressFromModelWithCustomerId()
+    {
+        $defaultBillingId = 1;
+        $defaultShippingId = 1;
+        $customerId = 1;
+        $attributeCode = 'attribute_code';
+
+        $addressModelMock = $this->getAddressMockForCreate();
+        $addressModelMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue(null));
+        $addressModelMock->expects($this->any())
+            ->method('getCustomerId')
+            ->will($this->returnValue($customerId));
+        $addressModelMock->expects($this->any())
+            ->method('getParentId');
+        $getData = function ($key, $index = null) use ($attributeCode, $customerId) {
+            $result = null;
+            switch($key) {
+                case $attributeCode:
+                    $result = 'some_data';
+                    break;
+                case 'customer_id':
+                    $result = $customerId;
+                    break;
+            }
+            return $result;
+        };
+        $addressModelMock->expects($this->any())
+            ->method('getData')
+            ->will($this->returnCallback($getData));
+        $attributeMock = $this->getMock(
+            'Magento\Customer\Service\V1\Data\Eav\AttributeMetadata',
+            array('getAttributeCode'),
+            array(),
+            '',
+            false
+        );
+        $attributeMock->expects($this->once())
+            ->method('getAttributeCode')
+            ->will($this->returnValue($attributeCode));
+
+
+        $addressMock = $this->getMock('Magento\Customer\Service\V1\Data\Address', array(), array(), '', false);
+        $this->metadataServiceMock->expects($this->once())
+            ->method('getAllAddressAttributeMetadata')
+            ->will($this->returnValue(array($attributeMock)));
+        $this->addressBuilderMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($addressMock));
+        $this->addressBuilderMock->expects($this->once())
+            ->method('setCustomerId')
+            ->with($this->equalTo($customerId));
+        $this->assertEquals(
+            $addressMock,
+            $this->model->createAddressFromModel($addressModelMock, $defaultBillingId, $defaultShippingId)
+        );
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getAddressMockForCreate()
+    {
+        $addressModelMock = $this->getMockForAbstractClass(
+            'Magento\Customer\Model\Address\AbstractAddress',
+            array(),
+            '',
+            false,
+            false,
+            false,
+            array(
+                'getId',
+                'getStreet',
+                'getRegion',
+                'getRegionId',
+                'getRegionCode',
+                'getCustomerId',
+                'getParentId',
+                'getData',
+                '__wakeup',
+            )
+        );
+        return $addressModelMock;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/AddressTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/AddressTest.php
new file mode 100644
index 00000000000..4ea1a39ba9f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/AddressTest.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model;
+
+class AddressTest extends \PHPUnit_Framework_TestCase
+{
+    const ORIG_CUSTOMER_ID = 1;
+    const ORIG_PARENT_ID = 2;
+
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Customer\Model\Address
+     */
+    protected $address;
+
+    /**
+     * @var \Magento\Customer\Model\Customer | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customer;
+
+    /**
+     * @var \Magento\Customer\Model\CustomerFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerFactory;
+
+    public function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $this->customer = $this->getMockBuilder('Magento\Customer\Model\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->customer->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(self::ORIG_CUSTOMER_ID));
+        $this->customer->expects($this->any())
+            ->method('load')
+            ->will($this->returnSelf());
+
+        $this->customerFactory = $this->getMockBuilder('Magento\Customer\Model\CustomerFactory')
+            ->setMethods(['create'])
+            ->getMock();
+        $this->customerFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->customer));
+
+        $this->resource = $this->getMockBuilder('Magento\Customer\Model\Resource\Address')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->address = $this->objectManager->getObject(
+            'Magento\Customer\Model\Address',
+            [
+                'customerFactory' => $this->customerFactory,
+                'resource' => $this->resource,
+            ]
+        );
+    }
+
+    public function testCustomerId()
+    {
+        $this->address->setParentId(self::ORIG_PARENT_ID);
+        $this->assertEquals(self::ORIG_PARENT_ID, $this->address->getCustomerId());
+
+        $this->address->setCustomerId(self::ORIG_CUSTOMER_ID);
+        $this->assertEquals(self::ORIG_CUSTOMER_ID, $this->address->getCustomerId());
+    }
+
+    public function testCustomer()
+    {
+        $this->address->unsetData('cusomer_id');
+        $this->assertFalse($this->address->getCustomer());
+
+        $this->address->setCustomerId(self::ORIG_CUSTOMER_ID);
+
+        $customer = $this->address->getCustomer();
+        $this->assertEquals(self::ORIG_CUSTOMER_ID, $customer->getId());
+
+        /** @var \Magento\Customer\Model\Customer $customer */
+        $customer = $this->getMockBuilder('Magento\Customer\Model\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $customer->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(self::ORIG_CUSTOMER_ID + 1));
+
+        $this->address->setCustomer($customer);
+        $this->assertEquals(self::ORIG_CUSTOMER_ID + 1, $this->address->getCustomerId());
+    }
+
+    public function testGetAttributes()
+    {
+        $resultValue = 'test';
+
+        $this->resource->expects($this->any())
+            ->method('loadAllAttributes')
+            ->will($this->returnSelf());
+        $this->resource->expects($this->any())
+            ->method('getSortedAttributes')
+            ->will($this->returnValue($resultValue));
+
+        $this->assertEquals($resultValue, $this->address->getAttributes());
+    }
+
+    public function testGetEntityTypeId()
+    {
+        $mockEntityType = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $mockEntityType->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(self::ORIG_CUSTOMER_ID));
+
+        $this->resource->expects($this->any())
+            ->method('getEntityType')
+            ->will($this->returnValue($mockEntityType));
+
+        $this->assertEquals(self::ORIG_CUSTOMER_ID, $this->address->getEntityTypeId());
+    }
+
+    public function testRegionId()
+    {
+        $this->address->setRegionId(1);
+        $this->assertEquals(1, $this->address->getRegionId());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/ConverterTest.php
index e4ffd74f61d..9994385d42c 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ConverterTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/ConverterTest.php
@@ -43,6 +43,21 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
      */
     protected $_objectManager;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\CustomerFactory
+     */
+    protected $customerFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Service\V1\Data\CustomerBuilder
+     */
+    protected $customerBuilderMock;
+
     public function setUp()
     {
         $this->_objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
@@ -77,6 +92,28 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+
+        $this->customerBuilderMock = $this->getMock(
+            'Magento\Customer\Service\V1\Data\CustomerBuilder',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $this->customerFactoryMock = $this->getMock(
+            'Magento\Customer\Model\CustomerFactory',
+            array('create'),
+            array(),
+            '',
+            false
+        );
+        $this->storeManagerMock = $this->getMock(
+            'Magento\Store\Model\StoreManagerInterface',
+            array(),
+            array(),
+            '',
+            false
+        );
     }
 
     public function testCreateCustomerFromModel()
@@ -142,7 +179,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
             'Magento\Customer\Model\CustomerFactory'
         )->disableOriginalConstructor()->getMock();
 
-        $converter = new Converter($customerBuilder, $customerFactory);
+        $converter = new Converter($customerBuilder, $customerFactory, $this->storeManagerMock);
         $customerDataObject = $converter->createCustomerFromModel($customerModelMock);
 
         $customerBuilder = $this->_objectManager->getObject(
@@ -165,6 +202,117 @@ class ConverterTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expectedCustomerData, $customerDataObject);
     }
 
+    protected function prepareGetCustomerModel($customerId)
+    {
+        $customerMock = $this->getMock('Magento\Customer\Model\Customer', array(), array(), '', false);
+        $customerMock->expects($this->once())
+            ->method('load')
+            ->with($customerId)
+            ->will($this->returnSelf());
+        $customerMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($customerId));
+
+        $this->customerFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($customerMock));
+
+        $converter = new Converter($this->customerBuilderMock, $this->customerFactoryMock, $this->storeManagerMock);
+        return $converter;
+    }
+
+    public function testGetCustomerModel()
+    {
+        $customerId = 1;
+        $converter = $this->prepareGetCustomerModel($customerId);
+        $this->assertInstanceOf('Magento\Customer\Model\Customer', $converter->getCustomerModel($customerId));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage No such entity with customerId
+     */
+    public function testGetCustomerModelException()
+    {
+        $customerId = 0;
+        $converter = $this->prepareGetCustomerModel($customerId);
+        $this->assertInstanceOf('Magento\Customer\Model\Customer', $converter->getCustomerModel($customerId));
+    }
+
+    /**
+     * @param $websiteId
+     * @param $customerEmail
+     * @param $customerId
+     */
+    protected function prepareGetCustomerModelByEmail($websiteId, $customerEmail, $customerId)
+    {
+        $customerMock = $this->getMock(
+            'Magento\Customer\Model\Customer',
+            array('setWebsiteId', 'loadByEmail', 'getId', '__wakeup'),
+            array(),
+            '',
+            false
+        );
+        $customerMock->expects($this->once())
+            ->method('setWebsiteId')
+            ->with($websiteId)
+            ->will($this->returnSelf());
+        $customerMock->expects($this->once())
+            ->method('loadByEmail')
+            ->with($customerEmail)
+            ->will($this->returnSelf());
+        $customerMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($customerId));
+
+        $this->customerFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($customerMock));
+    }
+
+    public function testGetCustomerModelByEmail()
+    {
+        $customerId = 1;
+        $websiteId = 1;
+        $customerEmail = 'test@example.com';
+        $this->prepareGetCustomerModelByEmail($websiteId, $customerEmail, $customerId);
+
+        $storeMock = $this->getMock('Magento\Store\Model\Store', array(), array(), '', false);
+        $storeMock->expects($this->once())
+            ->method('getWebsiteId')
+            ->will($this->returnValue($websiteId));
+
+        $this->storeManagerMock->expects($this->once())
+            ->method('getDefaultStoreView')
+            ->will($this->returnValue($storeMock));
+
+        $converter = new Converter($this->customerBuilderMock, $this->customerFactoryMock, $this->storeManagerMock);
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer',
+            $converter->getCustomerModelByEmail('test@example.com')
+        );
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage No such entity with email
+     */
+    public function testGetCustomerModelByEmailException()
+    {
+        $customerId = 0;
+        $websiteId = 1;
+        $customerEmail = 'test@example.com';
+        $this->prepareGetCustomerModelByEmail($websiteId, $customerEmail, $customerId);
+
+        $this->storeManagerMock->expects($this->never())->method('getDefaultStoreView');
+
+        $converter = new Converter($this->customerBuilderMock, $this->customerFactoryMock, $this->storeManagerMock);
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer',
+            $converter->getCustomerModelByEmail('test@example.com', $websiteId)
+        );
+    }
+
     /**
      * @param \PHPUnit_Framework_MockObject_MockObject $mock
      * @param array $valueMap
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
new file mode 100644
index 00000000000..8c23153608c
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/BillingTest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Customer\Model\Customer\Attribute\Backend;
+
+class BillingTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Billing
+     */
+    protected $testable;
+
+    public function setUp()
+    {
+        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        /** @var \Magento\Framework\Logger $logger */
+        $this->testable = new Billing($logger);
+    }
+
+    public function testBeforeSave()
+    {
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getDefaultBilling', 'unsetDefaultBilling'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getDefaultBilling')->will($this->returnValue(null));
+        $object->expects($this->once())->method('unsetDefaultBilling')->will($this->returnSelf());
+        /** @var \Magento\Framework\Object $object */
+
+        $this->testable->beforeSave($object);
+    }
+
+    public function testAfterSave()
+    {
+        $addressId = 1;
+        $attributeCode = 'attribute_code';
+        $defaultBilling = 'default billing address';
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getDefaultBilling', 'getAddresses', 'setDefaultBilling'))
+            ->getMock();
+
+        $address = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getPostIndex', 'getId'))
+            ->getMock();
+
+        $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->setMethods(array('__wakeup', 'getEntity', 'getAttributeCode'))
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $entity = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
+            ->setMethods(array('saveAttribute'))
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $attribute->expects($this->once())->method('getEntity')->will($this->returnValue($entity));
+        $attribute->expects($this->once())->method('getAttributeCode')->will($this->returnValue($attributeCode));
+        $entity->expects($this->once())->method('saveAttribute')->with($this->logicalOr($object, $attributeCode));
+        $address->expects($this->once())->method('getPostIndex')->will($this->returnValue($defaultBilling));
+        $address->expects($this->once())->method('getId')->will($this->returnValue($addressId));
+        $object->expects($this->once())->method('getDefaultBilling')->will($this->returnValue($defaultBilling));
+        $object->expects($this->once())->method('setDefaultBilling')->with($addressId)->will($this->returnSelf());
+        $object->expects($this->once())->method('getAddresses')->will($this->returnValue(array($address)));
+        /** @var \Magento\Framework\Object $object */
+        /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */
+
+        $this->testable->setAttribute($attribute);
+        $this->testable->afterSave($object);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/PasswordTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/PasswordTest.php
new file mode 100644
index 00000000000..05880064c98
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/PasswordTest.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model\Customer\Attribute\Backend;
+
+use Magento\Framework\Stdlib\String;
+
+class PasswordTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Password
+     */
+    protected $testable;
+
+    public function setUp()
+    {
+        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        $string = new String();
+        /** @var \Magento\Framework\Logger $logger */
+        $this->testable = new Password($logger, $string);
+    }
+
+    public function testValidatePositive()
+    {
+        $password = 'password';
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getPassword', 'getPasswordConfirm'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getPassword')->will($this->returnValue($password));
+        $object->expects($this->once())->method('getPasswordConfirm')->will($this->returnValue($password));
+        /** @var \Magento\Framework\Object $object */
+
+        $this->assertTrue($this->testable->validate($object));
+    }
+
+    public function passwordNegativeDataProvider()
+    {
+        return array(
+            'less-then-6-char' => array('less6'),
+            'with-space-prefix' => array(' normal_password'),
+            'with-space-suffix' => array('normal_password '),
+        );
+    }
+
+    /**
+     * @dataProvider passwordNegativeDataProvider
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testBeforeSaveNegative($password)
+    {
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getPassword'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getPassword')->will($this->returnValue($password));
+        /** @var \Magento\Framework\Object $object */
+
+        $this->testable->beforeSave($object);
+    }
+
+    public function testBeforeSavePositive()
+    {
+        $password = 'more-then-6';
+        $passwordHash = 'password-hash';
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getPassword', 'setPasswordHash', 'hashPassword'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getPassword')->will($this->returnValue($password));
+        $object->expects($this->once())->method('hashPassword')->will($this->returnValue($passwordHash));
+        $object->expects($this->once())->method('setPasswordHash')->with($passwordHash)->will($this->returnSelf());
+        /** @var \Magento\Framework\Object $object */
+
+        $this->testable->beforeSave($object);
+    }
+}
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
new file mode 100644
index 00000000000..15e5f857ee1
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/ShippingTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model\Customer\Attribute\Backend;
+
+class ShippingTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Shipping
+     */
+    protected $testable;
+
+    public function setUp()
+    {
+        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        /** @var \Magento\Framework\Logger $logger */
+        $this->testable = new Shipping($logger);
+    }
+
+    public function testBeforeSave()
+    {
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getDefaultShipping', 'unsetDefaultShipping'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getDefaultShipping')->will($this->returnValue(null));
+        $object->expects($this->once())->method('unsetDefaultShipping')->will($this->returnSelf());
+        /** @var \Magento\Framework\Object $object */
+
+        $this->testable->beforeSave($object);
+    }
+
+    public function testAfterSave()
+    {
+        $addressId = 1;
+        $attributeCode = 'attribute_code';
+        $defaultShipping = 'default Shipping address';
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getDefaultShipping', 'getAddresses', 'setDefaultShipping'))
+            ->getMock();
+
+        $address = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getPostIndex', 'getId'))
+            ->getMock();
+
+        $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+            ->setMethods(array('__wakeup', 'getEntity', 'getAttributeCode'))
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $entity = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
+            ->setMethods(array('saveAttribute'))
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $attribute->expects($this->once())->method('getEntity')->will($this->returnValue($entity));
+        $attribute->expects($this->once())->method('getAttributeCode')->will($this->returnValue($attributeCode));
+        $entity->expects($this->once())->method('saveAttribute')->with($this->logicalOr($object, $attributeCode));
+        $address->expects($this->once())->method('getPostIndex')->will($this->returnValue($defaultShipping));
+        $address->expects($this->once())->method('getId')->will($this->returnValue($addressId));
+        $object->expects($this->once())->method('getDefaultShipping')->will($this->returnValue($defaultShipping));
+        $object->expects($this->once())->method('setDefaultShipping')->with($addressId)->will($this->returnSelf());
+        $object->expects($this->once())->method('getAddresses')->will($this->returnValue(array($address)));
+        /** @var \Magento\Framework\Object $object */
+        /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */
+
+        $this->testable->setAttribute($attribute);
+        $this->testable->afterSave($object);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/StoreTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/StoreTest.php
new file mode 100644
index 00000000000..e640635f3d0
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/StoreTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model\Customer\Attribute\Backend;
+
+class StoreTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Store
+     */
+    protected $testable;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManager;
+
+    public function setUp()
+    {
+        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        /** @var \Magento\Framework\Logger $logger */
+        $storeManager = $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
+            ->getMock();
+        /** @var \Magento\Store\Model\StoreManagerInterface $storeManager */
+        $this->testable = new Store($logger, $storeManager);
+    }
+
+    public function testBeforeSaveWithId()
+    {
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getId'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getId')->will($this->returnValue(1));
+        /** @var \Magento\Framework\Object $object */
+
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer\Attribute\Backend\Store',
+            $this->testable->beforeSave($object)
+        );
+    }
+
+    public function testBeforeSave()
+    {
+        $storeId = 1;
+        $storeName = 'store';
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getId', 'hasStoreId', 'setStoreId', 'hasData', 'setData', 'getStoreId'))
+            ->getMock();
+
+        $store = $this->getMockBuilder('Magento\Framework\Object')->setMethods(array('getId', 'getName'))->getMock();
+        $store->expects($this->once())->method('getId')->will($this->returnValue($storeId));
+        $store->expects($this->once())->method('getName')->will($this->returnValue($storeName));
+
+        $this->storeManager->expects($this->exactly(2))
+            ->method('getStore')
+            ->will($this->returnValue($store));
+
+        $object->expects($this->once())->method('getId')->will($this->returnValue(false));
+        $object->expects($this->once())->method('hasStoreId')->will($this->returnValue(false));
+        $object->expects($this->once())->method('setStoreId')->with($storeId)->will($this->returnValue(false));
+        $object->expects($this->once())->method('getStoreId')->will($this->returnValue($storeId));
+        $object->expects($this->once())->method('hasData')->with('created_in')->will($this->returnValue(false));
+        $object->expects($this->once())
+            ->method('setData')
+            ->with($this->logicalOr('created_in', $storeName))
+            ->will($this->returnSelf());
+        /** @var \Magento\Framework\Object $object */
+
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer\Attribute\Backend\Store',
+            $this->testable->beforeSave($object)
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/WebsiteTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/WebsiteTest.php
new file mode 100644
index 00000000000..ac31a29e4e2
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Customer/Attribute/Backend/WebsiteTest.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Customer\Model\Customer\Attribute\Backend;
+
+class WebsiteTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Website
+     */
+    protected $testable;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManager;
+
+    public function setUp()
+    {
+        $logger = $this->getMockBuilder('Magento\Framework\Logger')->disableOriginalConstructor()->getMock();
+        /** @var \Magento\Framework\Logger $logger */
+        $storeManager = $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
+            ->getMock();
+        /** @var \Magento\Store\Model\StoreManagerInterface $storeManager */
+        $this->testable = new Website($logger, $storeManager);
+    }
+
+    public function testBeforeSaveWithId()
+    {
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('getId'))
+            ->getMock();
+
+        $object->expects($this->once())->method('getId')->will($this->returnValue(1));
+        /** @var \Magento\Framework\Object $object */
+
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer\Attribute\Backend\Website',
+            $this->testable->beforeSave($object)
+        );
+    }
+
+    public function testBeforeSave()
+    {
+        $websiteId = 1;
+        $object = $this->getMockBuilder('Magento\Framework\Object')
+            ->disableOriginalConstructor()
+            ->setMethods(array('hasData', 'setData'))
+            ->getMock();
+
+        $store = $this->getMockBuilder('Magento\Framework\Object')->setMethods(array('getWebsiteId'))->getMock();
+        $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId));
+
+        $this->storeManager->expects($this->once())
+            ->method('getStore')
+            ->will($this->returnValue($store));
+
+        $object->expects($this->once())->method('hasData')->with('website_id')->will($this->returnValue(false));
+        $object->expects($this->once())
+            ->method('setData')
+            ->with($this->logicalOr('website_id', $websiteId))
+            ->will($this->returnSelf());
+        /** @var \Magento\Framework\Object $object */
+
+        $this->assertInstanceOf(
+            'Magento\Customer\Model\Customer\Attribute\Backend\Website',
+            $this->testable->beforeSave($object)
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/CustomerTest.php
index 8699ebf1913..aafc348f8bb 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/CustomerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/CustomerTest.php
@@ -29,6 +29,9 @@
  */
 namespace Magento\Customer\Model;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class CustomerTest extends \PHPUnit_Framework_TestCase
 {
     /** @var \Magento\Customer\Model\Customer */
@@ -58,6 +61,18 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\Encryption\EncryptorInterface|\PHPUnit_Framework_MockObject_MockObject */
     protected $_encryptor;
 
+    /** @var \Magento\Customer\Model\AttributeFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeFactoryMock;
+
+    /** @var  \Magento\Customer\Model\Attribute|\PHPUnit_Framework_MockObject_MockObject */
+    protected $attributeCustomerMock;
+
+    /** @var  \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */
+    protected $registryMock;
+
+    /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resourceMock;
+
     protected function setUp()
     {
         $this->_website = $this->getMock('Magento\Store\Model\Website', array(), array(), '', false);
@@ -80,6 +95,32 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $this->attributeFactoryMock = $this->getMock(
+            'Magento\Customer\Model\AttributeFactory',
+            array('create'),
+            array(),
+            '',
+            false
+        );
+        $this->attributeCustomerMock = $this->getMock(
+            'Magento\Customer\Model\Attribute',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $this->resourceMock = $this->getMock(
+            '\Magento\Customer\Model\Resource\Customer', //'\Magento\Framework\Object',
+            array('getIdFieldName'),
+            array(),
+            '',
+            false,
+            false
+        );
+        $this->resourceMock->expects($this->any())
+            ->method('getIdFieldName')
+            ->will($this->returnValue('id'));
+        $this->registryMock = $this->getMock('Magento\Framework\Registry', array('registry'), array(), '', false);
         $this->_encryptor = $this->getMock('Magento\Framework\Encryption\EncryptorInterface');
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
         $this->_model = $helper->getObject(
@@ -89,7 +130,10 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
                 'config' => $this->_config,
                 'transportBuilder' => $this->_transportBuilderMock,
                 'scopeConfig' => $this->_scopeConfigMock,
-                'encryptor' => $this->_encryptor
+                'encryptor' => $this->_encryptor,
+                'attributeFactory' => $this->attributeFactoryMock,
+                'registry' => $this->registryMock,
+                'resource' => $this->resourceMock,
             )
         );
     }
@@ -223,4 +267,149 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
 
         $this->_model->sendPasswordResetNotificationEmail();
     }
+
+    /**
+     * @param $data
+     * @param $expected
+     *
+     * @dataProvider validateDataProvider
+     */
+    public function testValidate($data, $expected)
+    {
+        $this->attributeFactoryMock->expects($this->exactly(3))
+            ->method('create')
+            ->will($this->returnValue($this->attributeCustomerMock));
+        $this->attributeCustomerMock->expects($this->exactly(3))
+            ->method('loadByCode')
+            ->will($this->returnSelf());
+        $this->attributeCustomerMock->expects($this->exactly(3))
+            ->method('getIsRequired')
+            ->will($this->returnValue(true));
+        $this->_model->setData($data);
+        $this->assertEquals($expected, $this->_model->validate());
+    }
+
+    public function validateDataProvider()
+    {
+        $data = array(
+            'firstname' => 'First Name',
+            'lastname' => 'Last Name',
+            'email' => 'email@example.com',
+            'dob' => '01.01.1970',
+            'taxvat' => '10',
+            'gender' => 'm',
+        );
+        return array(
+            array(array_diff_key($data, array('firstname' => '')), array('The first name cannot be empty.')),
+            array(array_diff_key($data, array('lastname' => '')), array('The last name cannot be empty.')),
+            array(array_diff_key($data, array('email' => '')), array('Please correct this email address: "".')),
+            array(
+                array_merge($data, array('email' => 'wrong@email')),
+                array('Please correct this email address: "wrong@email".')
+            ),
+            array(array_diff_key($data, array('dob' => '')), array('The Date of Birth is required.')),
+            array(array_diff_key($data, array('taxvat' => '')), array('The TAX/VAT number is required.')),
+            array(array_diff_key($data, array('gender' => '')), array('Gender is required.')),
+            array($data, true),
+        );
+    }
+
+    public function testCanSkipConfirmationWithoutCustomerId()
+    {
+        $this->registryMock->expects($this->never())->method('registry');
+        $this->_model->setData('id', false);
+        $this->assertFalse($this->_model->canSkipConfirmation());
+    }
+
+    public function testCanSkipConfirmationWithoutSkip()
+    {
+        $idFieldName = 'id';
+        $this->registryMock->expects($this->once())
+            ->method('registry')
+            ->with('skip_confirmation_if_email')
+            ->will($this->returnValue(false));
+
+        $this->_model->setData($idFieldName, 1);
+        $this->assertFalse($this->_model->canSkipConfirmation());
+    }
+
+    public function testCanSkipConfirmation()
+    {
+        $customerEmail = 'test@example.com';
+        $this->registryMock->expects($this->once())
+            ->method('registry')
+            ->with('skip_confirmation_if_email')
+            ->will($this->returnValue($customerEmail));
+
+        $this->_model->setData(array(
+            'id' => 1,
+            'email' => $customerEmail,
+        ));
+        $this->assertTrue($this->_model->canSkipConfirmation());
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     * @expectedExceptionMessage Wrong transactional account email type
+     */
+    public function testSendNewAccountEmailException()
+    {
+        $this->_model->sendNewAccountEmail('test');
+    }
+
+    public function testSendNewAccountEmailWithoutStoreId()
+    {
+        $store = $this->getMock('Magento\Store\Model\Store', array(), array(), '', false);
+        $website = $this->getMock('Magento\Store\Model\Website', array(), array(), '', false);
+        $website->expects($this->once())
+            ->method('getStoreIds')
+            ->will($this->returnValue(array(1,2,3,4)));
+        $this->_storeManager->expects($this->once())
+            ->method('getWebsite')
+            ->with(1)
+            ->will($this->returnValue($website));
+        $this->_storeManager->expects($this->once())
+            ->method('getStore')
+            ->with(1)
+            ->will($this->returnValue($store));
+
+        $this->_config->expects($this->exactly(3))
+            ->method('getAttribute')
+            ->will($this->returnValue($this->_attribute));
+
+        $this->_attribute->expects($this->exactly(3))
+            ->method('getIsVisible')
+            ->will($this->returnValue(true));
+
+        $methods = array(
+            'setTemplateIdentifier',
+            'setTemplateOptions',
+            'setTemplateVars',
+            'setFrom',
+            'addTo',
+        );
+        foreach ($methods as $method) {
+            $this->_transportBuilderMock->expects($this->once())
+                ->method($method)
+                ->will($this->returnSelf());
+        }
+        $transportMock = $this->getMock('Magento\Framework\Mail\TransportInterface', array(), array(), '', false);
+        $transportMock->expects($this->once())
+            ->method('sendMessage')
+            ->will($this->returnSelf());
+        $this->_transportBuilderMock->expects($this->once())
+            ->method('getTransport')
+            ->will($this->returnValue($transportMock));
+
+        $this->_model->setData(array(
+                'website_id' => 1,
+                'store_id'   => 1,
+                'email'      => 'email@example.com',
+                'firstname'  => 'FirstName',
+                'lastname'   => 'LastName',
+                'middlename' => 'MiddleName',
+                'prefix'     => 'Prefix',
+        ));
+        $this->_model->sendNewAccountEmail('registered');
+    }
 }
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 701739639b2..2e95455706d 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
@@ -62,8 +62,8 @@ class ServiceCollectionTest extends \PHPUnit_Framework_TestCase
         );
         $this->groupServiceMock = $this->getMockBuilder('\Magento\Customer\Service\V1\CustomerGroupServiceInterface')
             ->getMock();
-        $this->searchResults = $this->objectManager
-            ->getObject('\Magento\Customer\Service\V1\Data\SearchResultsBuilder')->create();
+        $this->searchResults = $this->objectManager->getObject('Magento\Customer\Service\V1\Data\SearchResultsBuilder')
+            ->create();
 
         $this->serviceCollection = $this->objectManager
             ->getObject(
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/SessionTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/SessionTest.php
index a95ac2e6046..419e2229771 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/SessionTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Model/SessionTest.php
@@ -47,6 +47,16 @@ class SessionTest extends \PHPUnit_Framework_TestCase
      */
     protected $_httpContextMock;
 
+    /**
+     * @var \Magento\Framework\UrlFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $urlFactoryMock;
+
+    /**
+     * @var \Magento\Customer\Service\V1\CustomerAccountService|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $customerAccountServiceMock;
+
     /**
      * @var \Magento\Customer\Model\Session
      */
@@ -58,13 +68,24 @@ class SessionTest extends \PHPUnit_Framework_TestCase
         $this->_storageMock = $this->getMock('Magento\Customer\Model\Session\Storage', [], [], '', false);
         $this->_eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
         $this->_httpContextMock = $this->getMock('Magento\Framework\App\Http\Context', [], [], '', false);
+        $this->urlFactoryMock = $this->getMock('Magento\Framework\UrlFactory', [], [], '', false);
+        $this->customerAccountServiceMock = $this->getMock(
+            'Magento\Customer\Service\V1\CustomerAccountService',
+            [],
+            [],
+            '',
+            false
+        );
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = $helper->getObject('Magento\Customer\Model\Session',
+        $this->_model = $helper->getObject(
+            'Magento\Customer\Model\Session',
             [
                 'converter' => $this->_converterMock,
                 'storage' => $this->_storageMock,
                 'eventManager' => $this->_eventManagerMock,
-                'httpContext' => $this->_httpContextMock
+                'httpContext' => $this->_httpContextMock,
+                'urlFactory' => $this->urlFactoryMock,
+                'customerAccountService' => $this->customerAccountServiceMock,
             ]
         );
     }
@@ -109,4 +130,92 @@ class SessionTest extends \PHPUnit_Framework_TestCase
         $this->assertSame($customer, $this->_model->getCustomer());
     }
 
+    public function testAuthenticate()
+    {
+        $urlMock = $this->getMock('Magento\Framework\Url', array(), array(), '', false);
+        $urlMock->expects($this->exactly(2))
+            ->method('getUrl')
+            ->will($this->returnValue(''));
+        $urlMock->expects($this->once())
+            ->method('getRebuiltUrl')
+            ->will($this->returnValue(''));
+        $this->urlFactoryMock->expects($this->exactly(3))
+            ->method('create')
+            ->will($this->returnValue($urlMock));
+
+        $responseMock = $this->getMock('Magento\Framework\App\Response\Http', array(), array(), '', false);
+        $responseMock->expects($this->once())
+            ->method('setRedirect')
+            ->with('')
+            ->will($this->returnValue(''));
+
+        $actionMock = $this->getMock('Magento\Framework\App\Action\Action', array(), array(), '', false);
+        $actionMock->expects($this->once())
+            ->method('getResponse')
+            ->will($this->returnValue($responseMock));
+
+        $this->assertFalse($this->_model->authenticate($actionMock));
+    }
+
+    public function testLoginById()
+    {
+        $customerId = 1;
+
+        $customerDataMock = $this->prepareLoginDataMock($customerId);
+
+        $this->customerAccountServiceMock->expects($this->once())
+            ->method('getCustomer')
+            ->with($this->equalTo($customerId))
+            ->will($this->returnValue($customerDataMock));
+
+        $this->assertTrue($this->_model->loginById($customerId));
+    }
+
+    public function testLogin()
+    {
+        $customerId = 1;
+        $username = 'TestName';
+        $password = 'TestPassword';
+
+        $customerDataMock = $this->prepareLoginDataMock($customerId);
+
+        $this->customerAccountServiceMock->expects($this->once())
+            ->method('authenticate')
+            ->with($this->equalTo($username), $this->equalTo($password))
+            ->will($this->returnValue($customerDataMock));
+
+        $this->assertTrue($this->_model->login($username, $password));
+    }
+
+    /**
+     * @param $customerId
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function prepareLoginDataMock($customerId)
+    {
+        $customerDataMock = $this->getMock('Magento\Customer\Service\V1\Data\Customer', array(), array(), '', false);
+        $customerDataMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($customerId));
+
+        $customerMock = $this->getMock('Magento\Customer\Model\Customer', array(), array(), '', false);
+        $customerMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($customerId));
+        $customerMock->expects($this->once())
+            ->method('isConfirmationRequired')
+            ->will($this->returnValue(true));
+        $customerMock->expects($this->never())
+            ->method('getConfirmation')
+            ->will($this->returnValue($customerId));
+
+        $this->_converterMock->expects($this->once())
+            ->method('createCustomerModel')
+            ->with($customerDataMock)
+            ->will($this->returnValue($customerMock));
+
+        $this->_httpContextMock->expects($this->exactly(3))
+            ->method('setValue');
+        return $customerDataMock;
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php b/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
index 7caf2cbc475..5da07017804 100755
--- a/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAccountServiceTest.php
@@ -85,6 +85,11 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
      */
     private $_storeMock;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\Website
+     */
+    private $_websiteMock;
+
     /**
      * @var \Magento\Customer\Service\V1\Data\CustomerBuilder
      */
@@ -156,8 +161,8 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock = $this->getMockBuilder(
             'Magento\Customer\Model\CustomerFactory'
         )->disableOriginalConstructor()->setMethods(
-                array('create')
-            )->getMock();
+            array('create')
+        )->getMock();
 
         $this->_customerModelMock = $this->getMockBuilder('Magento\Customer\Model\Customer')
             ->disableOriginalConstructor()
@@ -209,6 +214,7 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
                     'changeResetPasswordLinkToken',
                     'sendPasswordResetConfirmationEmail',
                     'sendPasswordResetNotificationEmail',
+                    'sendPasswordReminderEmail',
                     'delete'
                 )
             )->getMock();
@@ -237,10 +243,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getCustomCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue(array())
-            );
+            'getCustomCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue(array())
+        );
 
         $this->_customerBuilder = $this->_objectManager->getObject(
             'Magento\Customer\Service\V1\Data\CustomerBuilder',
@@ -260,7 +266,11 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             ]
         );
 
-        $this->_converter = new Converter($this->_customerBuilder, $this->_customerFactoryMock);
+        $this->_converter = new Converter(
+            $this->_customerBuilder,
+            $this->_customerFactoryMock,
+            $this->_storeManagerMock
+        );
 
         $this->_customerRegistry = $this->getMockBuilder('\Magento\Customer\Model\CustomerRegistry')
             ->setMethods(['retrieve', 'retrieveByEmail'])
@@ -320,10 +330,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         // Assertions
         $this->_customerModelMock->expects($this->once())->method('save');
@@ -351,10 +361,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         // Assertions
         $this->_customerModelMock->expects($this->never())->method('save');
@@ -371,7 +381,8 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             ->expects($this->any())
             ->method('retrieve')
             ->will($this->throwException(
-                new NoSuchEntityException(NoSuchEntityException::MESSAGE_SINGLE_FIELD,
+                new NoSuchEntityException(
+                    NoSuchEntityException::MESSAGE_SINGLE_FIELD,
                     [
                         'fieldName' => 'customerId',
                         'fieldValue' => 1,
@@ -408,10 +419,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         // Assertions
         $this->_customerModelMock->expects($this->never())->method('save');
@@ -438,19 +449,19 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         // Assertions/Mocking
         $this->_customerModelMock->expects(
             $this->once()
         )->method(
-                'save'
-            )->will(
-                $this->throwException(new \Exception('DB is down'))
-            );
+            'save'
+        )->will(
+            $this->throwException(new \Exception('DB is down'))
+        );
         $this->_customerModelMock->expects($this->once())->method('setConfirmation');
 
         $customerService = $this->_createService();
@@ -473,10 +484,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $customerService = $this->_createService();
 
@@ -486,11 +497,12 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @expectedException \Magento\Framework\Exception\AuthenticationException
-     * @expectedExceptionMessage exception message
+     * @dataProvider authenticateException
      */
-    public function testLoginAccountWithException()
+    public function testLoginAccountWithException($eName, $eCode)
     {
+        $eMessage = 'exception message';
+        $this->setExpectedException($eName, $eMessage);
         $this->_mockReturnValue(
             $this->_customerModelMock,
             array('getId' => self::ID, 'load' => $this->_customerModelMock)
@@ -501,22 +513,37 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         )->method(
             'authenticate'
         )->will(
-            $this->throwException(new \Magento\Framework\Model\Exception('exception message'))
+            $this->throwException(new \Magento\Framework\Model\Exception($eMessage, $eCode))
         );
 
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $customerService = $this->_createService();
 
         $customerService->authenticate(self::EMAIL, self::PASSWORD, self::WEBSITE_ID);
     }
 
+    public function authenticateException()
+    {
+        return array(
+            array(
+                '\Magento\Framework\Exception\EmailNotConfirmedException',
+                \Magento\Customer\Model\Customer::EXCEPTION_EMAIL_NOT_CONFIRMED
+            ),
+            array(
+                '\Magento\Framework\Exception\InvalidEmailOrPasswordException',
+                \Magento\Customer\Model\Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD
+            ),
+            array('\Magento\Framework\Exception\AuthenticationException', 0),
+        );
+    }
+
     public function testValidateResetPasswordLinkToken()
     {
         $resetToken = 'lsdj579slkj5987slkj595lkj';
@@ -533,10 +560,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $customerService = $this->_createService();
 
@@ -562,10 +589,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $customerService = $this->_createService();
 
@@ -592,10 +619,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $customerService = $this->_createService();
 
@@ -610,7 +637,8 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             ->expects($this->any())
             ->method('retrieve')
             ->will($this->throwException(
-                new NoSuchEntityException(NoSuchEntityException::MESSAGE_SINGLE_FIELD,
+                new NoSuchEntityException(
+                    NoSuchEntityException::MESSAGE_SINGLE_FIELD,
                     [
                         'fieldName' => 'customerId',
                         'fieldValue' => 1,
@@ -661,12 +689,60 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+    protected function prepareInitiatePasswordReset($method)
+    {
+        $storeId = 42;
+
+        $this->_customerModelMock->expects($this->once())
+            ->method($method);
+        $this->_customerModelMock->expects($this->atLeastOnce())
+            ->method('getStoreId')
+            ->will($this->returnValue($storeId));
+        $this->_urlMock->expects($this->once())
+            ->method('setScope')->with($storeId)
+            ->will($this->returnSelf());
+    }
+
     public function testSendPasswordResetLink()
+    {
+        $email = 'foo@example.com';
+        $this->prepareInitiatePasswordReset('sendPasswordResetConfirmationEmail');
+
+        $customerService = $this->_createService();
+
+        $customerService->initiatePasswordReset(
+            $email,
+            CustomerAccountServiceInterface::EMAIL_RESET,
+            self::WEBSITE_ID
+        );
+    }
+
+    public function testSendPasswordReminderLinkWithoutWebsite()
+    {
+        $email = 'foo@example.com';
+
+        $this->prepareInitiatePasswordReset('sendPasswordReminderEmail');
+
+        $customerService = $this->_createService();
+
+        $customerService->initiatePasswordReset(
+            $email,
+            CustomerAccountServiceInterface::EMAIL_REMINDER
+        );
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @expectedExceptionMessage Invalid value of "" provided for the email type field.
+     */
+    public function testInitiatePasswordResetWithException()
     {
         $email = 'foo@example.com';
         $storeId = 42;
 
-        $this->_customerModelMock->expects($this->once())
+        $this->_customerModelMock->expects($this->never())
+            ->method('sendPasswordReminderEmail');
+        $this->_customerModelMock->expects($this->never())
             ->method('sendPasswordResetConfirmationEmail');
         $this->_customerModelMock->expects($this->atLeastOnce())
             ->method('getStoreId')
@@ -675,11 +751,17 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             ->method('setScope')->with($storeId)
             ->will($this->returnSelf());
 
+        $this->_storeMock->expects($this->never())
+            ->method('getWebSiteId');
+
+        $this->_storeMock->expects($this->never())
+            ->method('getWebSiteId');
+
         $customerService = $this->_createService();
 
         $customerService->initiatePasswordReset(
             $email,
-            CustomerAccountServiceInterface::EMAIL_RESET,
+            '',
             self::WEBSITE_ID
         );
     }
@@ -787,10 +869,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->once())
             ->method('setRpToken')
@@ -832,10 +914,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->once())
             ->method('setRpToken')
@@ -879,10 +961,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->never())->method('setRpToken');
         $this->_customerModelMock->expects($this->never())->method('setRpTokenCreatedAt');
@@ -914,10 +996,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->never())->method('setRpToken');
         $this->_customerModelMock->expects($this->never())->method('setRpTokenCreatedAt');
@@ -938,13 +1020,15 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             ->expects($this->any())
             ->method('retrieve')
             ->will($this->throwException(
-                new NoSuchEntityException(NoSuchEntityException::MESSAGE_SINGLE_FIELD,
+                new NoSuchEntityException(
+                    NoSuchEntityException::MESSAGE_SINGLE_FIELD,
                     [
                         'fieldName' => 'customerId',
                         'fieldValue' => $invalidCustomerId,
                     ]
                 )
-        ));
+            )
+        );
 
         $this->_customerModelMock->expects($this->never())->method('setRpToken');
         $this->_customerModelMock->expects($this->never())->method('setRpTokenCreatedAt');
@@ -977,10 +1061,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->never())->method('setRpToken');
         $this->_customerModelMock->expects($this->never())->method('setRpTokenCreatedAt');
@@ -1003,17 +1087,17 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerModelMock->expects(
             $this->any()
         )->method(
-                'isConfirmationRequired'
-            )->will(
-                $this->returnValue(true)
-            );
+            'isConfirmationRequired'
+        )->will(
+            $this->returnValue(true)
+        );
         $this->_customerModelMock->expects(
             $this->any()
         )->method(
-                'getConfirmation'
-            )->will(
-                $this->returnValue('123abc')
-            );
+            'getConfirmation'
+        )->will(
+            $this->returnValue('123abc')
+        );
 
         $customerService = $this->_createService();
         $customerService->resendConfirmation('email', 1);
@@ -1023,7 +1107,8 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
     {
         $email = 'no.customer@example.com';
         $websiteId = self::WEBSITE_ID;
-        $exception = new NoSuchEntityException(NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
+        $exception = new NoSuchEntityException(
+            NoSuchEntityException::MESSAGE_DOUBLE_FIELDS,
             [
                 'fieldName' => 'email',
                 'fieldValue' => 'email@no.customer',
@@ -1090,27 +1175,27 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             $this->_customerModelMock->expects(
                 $this->once()
             )->method(
-                    'getConfirmation'
-                )->will(
-                    $this->returnValue(false)
-                );
+                'getConfirmation'
+            )->will(
+                $this->returnValue(false)
+            );
         } else {
             $this->_customerModelMock->expects(
                 $this->once()
             )->method(
-                    'getConfirmation'
-                )->will(
-                    $this->returnValue(true)
-                );
+                'getConfirmation'
+            )->will(
+                $this->returnValue(true)
+            );
         }
         if (CustomerAccountServiceInterface::ACCOUNT_CONFIRMATION_REQUIRED == $expected) {
             $this->_customerModelMock->expects(
                 $this->once()
             )->method(
-                    'isConfirmationRequired'
-                )->will(
-                    $this->returnValue(true)
-                );
+                'isConfirmationRequired'
+            )->will(
+                $this->returnValue(true)
+            );
         } elseif (CustomerAccountServiceInterface::ACCOUNT_CONFIRMED != $expected) {
             $this->_customerModelMock->expects(
                 $this->once()
@@ -1159,10 +1244,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerModelMock->expects(
             $this->once()
         )->method(
-                'isDeleteable'
-            )->will(
-                $this->returnValue($isBoolean)
-            );
+            'isDeleteable'
+        )->will(
+            $this->returnValue($isBoolean)
+        );
 
         $customerService = $this->_createService();
         $this->assertEquals($isBoolean, $customerService->canDelete(self::ID));
@@ -1195,10 +1280,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_converter = $this->getMock('Magento\Customer\Model\Converter', [], [], '', false);
         $this->_converter
@@ -1227,10 +1312,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue($mockAttribute)
-            );
+            'getCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue($mockAttribute)
+        );
 
         // verify
         $this->_converter
@@ -1269,10 +1354,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_mockReturnValue(
             $this->_customerModelMock,
@@ -1290,10 +1375,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue($mockAttribute)
-            );
+            'getCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue($mockAttribute)
+        );
 
         // verify
         $this->_converter
@@ -1336,10 +1421,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_mockReturnValue(
             $this->_customerModelMock,
@@ -1357,10 +1442,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue($mockAttribute)
-            );
+            'getCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue($mockAttribute)
+        );
 
         $this->_converter
             ->expects($this->once())
@@ -1466,10 +1551,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerModelMock->expects(
             $this->any()
         )->method(
-                'load'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'load'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_mockReturnValue(
             $this->_customerModelMock,
@@ -1486,20 +1571,20 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $attributeModelMock->expects(
             $this->any()
         )->method(
-                'getAttributeCode'
-            )->will(
-                $this->returnValue('attribute_code')
-            );
+            'getAttributeCode'
+        )->will(
+            $this->returnValue('attribute_code')
+        );
 
         $this->_customerModelMock->expects(
             $this->any()
         )->method(
-                'getData'
-            )->with(
-                $this->equalTo('attribute_code')
-            )->will(
-                $this->returnValue('ATTRIBUTE_VALUE')
-            );
+            'getData'
+        )->with(
+            $this->equalTo('attribute_code')
+        )->will(
+            $this->returnValue('ATTRIBUTE_VALUE')
+        );
 
         $this->_customerFactoryMock->expects(
             $this->any()
@@ -1532,10 +1617,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->atLeastOnce()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerModelMock->expects($this->any())->method('load')->will($this->returnSelf());
 
@@ -1547,17 +1632,17 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getAllCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue(array())
-            );
+            'getAllCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue(array())
+        );
 
         $customerService = $this->_createService();
         $filterBuilder = $this->_objectManager->getObject('\Magento\Framework\Service\V1\Data\FilterBuilder');
@@ -1608,26 +1693,26 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerFactoryMock->expects(
             $this->any()
         )->method(
-                'create'
-            )->will(
-                $this->returnValue($this->_customerModelMock)
-            );
+            'create'
+        )->will(
+            $this->returnValue($this->_customerModelMock)
+        );
 
         $this->_customerAddressServiceMock->expects(
             $this->once()
         )->method(
-                'getAddresses'
-            )->will(
-                $this->returnValue(array())
-            );
+            'getAddresses'
+        )->will(
+            $this->returnValue(array())
+        );
 
         $this->_customerMetadataService->expects(
             $this->any()
         )->method(
-                'getAllCustomerAttributeMetadata'
-            )->will(
-                $this->returnValue(array())
-            );
+            'getAllCustomerAttributeMetadata'
+        )->will(
+            $this->returnValue(array())
+        );
 
         $customerService = $this->_createService();
         $filterBuilder = $this->_objectManager->getObject('\Magento\Framework\Service\V1\Data\FilterBuilder');
@@ -1661,10 +1746,10 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_customerAddressServiceMock->expects(
             $this->once()
         )->method(
-                'getAddresses'
-            )->will(
-                $this->returnValue(array($addressMock))
-            );
+            'getAddresses'
+        )->will(
+            $this->returnValue(array($addressMock))
+        );
         $customerDetails = $service->getCustomerDetails(1);
         $this->assertEquals($customerMock, $customerDetails->getCustomer());
         $this->assertEquals(array($addressMock), $customerDetails->getAddresses());
@@ -1701,17 +1786,17 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->_converter->expects(
             $this->any()
         )->method(
-                'createCustomerFromModel'
-            )->will(
-                $this->returnValue($customerMock)
-            );
+            'createCustomerFromModel'
+        )->will(
+            $this->returnValue($customerMock)
+        );
         $this->_customerAddressServiceMock->expects(
             $this->any()
         )->method(
-                'getAddresses'
-            )->will(
-                $this->returnValue(array($addressMock))
-            );
+            'getAddresses'
+        )->will(
+            $this->returnValue(array($addressMock))
+        );
         $service->getCustomerDetails(1);
     }
 
@@ -1922,6 +2007,103 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
         $this->assertTrue($customerService->deleteCustomerByEmail(self::EMAIL, $defaultWebsiteId));
     }
 
+    /**
+     * @expectedException \Magento\Framework\Exception\State\InputMismatchException
+     * @expectedExceptionMessage Customer with the same email already exists in associated website.
+     */
+    public function testCreateCustomerWithPasswordHashEmailExists()
+    {
+        $storeId = 5;
+        $customerData = array(
+            'customer_id' => 0,
+            'email' => self::EMAIL,
+            'firstname' => self::FIRSTNAME,
+            'lastname' => self::LASTNAME,
+            'website_id' => self::WEBSITE_ID,
+            'create_in' => 'Admin',
+            'password' => 'password'
+        );
+        $this->_customerBuilder->populateWithArray($customerData);
+        $customerEntity = $this->_customerBuilder->create();
+        $customerDetails = $this->_customerDetailsBuilder->setCustomer($customerEntity)->create();
+
+        $this->_storeMock->expects($this->once())
+            ->method('getId')
+            ->will($this->returnValue($storeId));
+
+        $this->_websiteMock->expects($this->once())
+            ->method('getDefaultStore')
+            ->will($this->returnValue($this->_storeMock));
+
+        $this->_storeManagerMock->expects($this->once())
+            ->method('getWebsite')
+            ->with($this->equalTo(self::WEBSITE_ID))
+            ->will($this->returnValue($this->_websiteMock));
+
+        $this->_converter = $this->getMock('Magento\Customer\Model\Converter', ['createCustomerModel'], [], '', false);
+        $this->_converter->expects($this->once())
+            ->method('createCustomerModel')
+            ->will(
+                $this->throwException(
+                    new \Magento\Customer\Exception(
+                        'exception message',
+                        \Magento\Customer\Model\Customer::EXCEPTION_EMAIL_EXISTS
+                    )
+                )
+            );
+
+        $customerService = $this->_createService();
+        $customerService->createCustomerWithPasswordHash($customerDetails, '', '');
+    }
+
+    /**
+     * @expectedException \Magento\Customer\Exception
+     * @expectedExceptionMessage exception message
+     */
+    public function testCreateCustomerWithPasswordHashException()
+    {
+        $storeId = 5;
+        $customerData = array(
+            'id' => self::ID,
+            'email' => self::EMAIL,
+            'firstname' => self::FIRSTNAME,
+            'lastname' => self::LASTNAME,
+            'store_id' => $storeId,
+            'website_id' => self::WEBSITE_ID
+        );
+        $this->_customerBuilder->populateWithArray($customerData);
+        $customerEntity = $this->_customerBuilder->create();
+        $customerDetails = $this->_customerDetailsBuilder->setCustomer($customerEntity)->create();
+
+        $this->_storeManagerMock->expects($this->once())
+            ->method('getStores')
+            ->will($this->returnValue(array()));
+
+        $this->_converter = $this->getMock(
+            'Magento\Customer\Model\Converter',
+            array('getCustomerModel', 'createCustomerModel'),
+            array(),
+            '',
+            false
+        );
+        $this->_converter->expects($this->once())
+            ->method('getCustomerModel')
+            ->will($this->returnValue($this->_customerModelMock));
+        $this->_converter->expects($this->once())
+            ->method('createCustomerModel')
+            ->will(
+                $this->throwException(
+                    new \Magento\Customer\Exception(
+                        'exception message',
+                        0
+                    )
+                )
+            );
+
+        $customerService = $this->_createService();
+        $customerService->createCustomerWithPasswordHash($customerDetails, '', '');
+    }
+
     private function _setupStoreMock()
     {
         $this->_storeManagerMock = $this->getMockBuilder(
@@ -1932,13 +2114,21 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
             '\Magento\Store\Model\Store'
         )->disableOriginalConstructor()->getMock();
 
+        $this->_websiteMock = $this->getMock(
+            'Magento\Store\Model\Website',
+            array('__wakeup', 'getDefaultStore'),
+            array(),
+            '',
+            false
+        );
+
         $this->_storeManagerMock->expects(
             $this->any()
         )->method(
-                'getStore'
-            )->will(
-                $this->returnValue($this->_storeMock)
-            );
+            'getStore'
+        )->will(
+            $this->returnValue($this->_storeMock)
+        );
     }
 
 
@@ -1958,13 +2148,16 @@ class CustomerAccountServiceTest extends \PHPUnit_Framework_TestCase
      */
     private function _createService()
     {
-        $customerService = $this->_objectManager->getObject('Magento\Customer\Service\V1\CustomerAccountService',
+        $searchResultBuilder = $this->_objectManager->getObject(
+            'Magento\Customer\Service\V1\Data\SearchResultsBuilder'
+        );
+        $customerService = $this->_objectManager->getObject(
+            'Magento\Customer\Service\V1\CustomerAccountService',
             [
                 'customerFactory' => $this->_customerFactoryMock,
                 'storeManager' => $this->_storeManagerMock,
                 'converter' => $this->_converter,
-                'searchResultsBuilder' => $this->_objectManager
-                        ->getObject('\Magento\Customer\Service\V1\Data\SearchResultsBuilder'),
+                'searchResultsBuilder' => $searchResultBuilder,
                 'customerBuilder' => $this->_customerBuilder,
                 'customerDetailsBuilder' => $this->_customerDetailsBuilder,
                 'customerAddressService' => $this->_customerAddressServiceMock,
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAddressServiceTest.php b/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAddressServiceTest.php
index ab041c6ab0b..56e4c24f2e7 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAddressServiceTest.php
+++ b/dev/tests/unit/testsuite/Magento/Customer/Service/V1/CustomerAddressServiceTest.php
@@ -270,7 +270,8 @@ class CustomerAddressServiceTest extends \PHPUnit_Framework_TestCase
 
         $this->_customerConverter = new \Magento\Customer\Model\Converter(
             $customerBuilder,
-            $this->_customerFactoryMock
+            $this->_customerFactoryMock,
+            $this->_storeManagerMock
         );
 
         $this->_addressConverterMock = $this->getMockBuilder(
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
similarity index 92%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
index 1d67e00218c..f5bcf3d1f82 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/AddressTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/AddressTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
 class AddressTest extends \PHPUnit_Framework_TestCase
 {
@@ -93,7 +93,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->_objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = new \Magento\Customer\Model\ImportExport\Export\Address(
+        $this->_model = new \Magento\CustomerImportExport\Model\Export\Address(
             $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'),
             $storeManager,
             $this->getMock('Magento\ImportExport\Model\Export\Factory', array(), array(), '', false),
@@ -108,7 +108,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false),
             $this->getMock('Magento\Customer\Model\Resource\Customer\CollectionFactory', array(), array(), '', false),
             $this->getMock(
-                'Magento\Customer\Model\ImportExport\Export\CustomerFactory',
+                'Magento\CustomerImportExport\Model\Export\CustomerFactory',
                 array(),
                 array(),
                 '',
@@ -264,7 +264,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     /**
      * Test for method exportItem()
      *
-     * @covers \Magento\Customer\Model\ImportExport\Export\Address::exportItem
+     * @covers \Magento\CustomerImportExport\Model\Export\Address::exportItem
      */
     public function testExportItem()
     {
@@ -302,19 +302,19 @@ class AddressTest extends \PHPUnit_Framework_TestCase
      */
     public function validateWriteRow(array $row)
     {
-        $billingColumn = \Magento\Customer\Model\ImportExport\Export\Address::COLUMN_NAME_DEFAULT_BILLING;
+        $billingColumn = \Magento\CustomerImportExport\Model\Export\Address::COLUMN_NAME_DEFAULT_BILLING;
         $this->assertEquals($this->_customerData['default_billing'], $row[$billingColumn]);
 
-        $shippingColumn = \Magento\Customer\Model\ImportExport\Export\Address::COLUMN_NAME_DEFAULT_SHIPPING;
+        $shippingColumn = \Magento\CustomerImportExport\Model\Export\Address::COLUMN_NAME_DEFAULT_SHIPPING;
         $this->assertEquals($this->_customerData['default_shipping'], $row[$shippingColumn]);
 
-        $idColumn = \Magento\Customer\Model\ImportExport\Export\Address::COLUMN_ADDRESS_ID;
+        $idColumn = \Magento\CustomerImportExport\Model\Export\Address::COLUMN_ADDRESS_ID;
         $this->assertEquals($this->_addressData['id'], $row[$idColumn]);
 
-        $emailColumn = \Magento\Customer\Model\ImportExport\Export\Address::COLUMN_EMAIL;
+        $emailColumn = \Magento\CustomerImportExport\Model\Export\Address::COLUMN_EMAIL;
         $this->assertEquals($this->_customerData['email'], $row[$emailColumn]);
 
-        $websiteColumn = \Magento\Customer\Model\ImportExport\Export\Address::COLUMN_WEBSITE;
+        $websiteColumn = \Magento\CustomerImportExport\Model\Export\Address::COLUMN_WEBSITE;
         $this->assertEquals($this->_websites[$this->_customerData['website_id']], $row[$websiteColumn]);
 
         $this->assertEquals($this->_addressData[self::ATTRIBUTE_CODE], $row[self::ATTRIBUTE_CODE]);
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
similarity index 98%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
index d90a834810a..a3b31172204 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Export/CustomerTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Export;
+namespace Magento\CustomerImportExport\Model\Export;
 
 class CustomerTest extends \PHPUnit_Framework_TestCase
 {
@@ -202,7 +202,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
     /**
      * Test for method exportItem()
      *
-     * @covers \Magento\Customer\Model\ImportExport\Export\Customer::exportItem
+     * @covers \Magento\CustomerImportExport\Model\Export\Customer::exportItem
      */
     public function testExportItem()
     {
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AbstractCustomerTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AbstractCustomerTest.php
similarity index 92%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AbstractCustomerTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AbstractCustomerTest.php
index 4d4013cd319..033bc5ae91b 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AbstractCustomerTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AbstractCustomerTest.php
@@ -23,16 +23,16 @@
  */
 
 /**
- * Test class for \Magento\Customer\Model\ImportExport\Import\AbstractCustomer
+ * Test class for \Magento\CustomerImportExport\Model\Import\AbstractCustomer
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
 {
     /**
      * Abstract customer export model
      *
-     * @var \Magento\Customer\Model\ImportExport\Import\AbstractCustomer|PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\CustomerImportExport\Model\Import\AbstractCustomer|PHPUnit_Framework_MockObject_MockObject
      */
     protected $_model;
 
@@ -80,7 +80,7 @@ class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
     /**
      * Create mock for abstract customer model class
      *
-     * @return \Magento\Customer\Model\ImportExport\Import\AbstractCustomer|PHPUnit_Framework_MockObject_MockObject
+     * @return \Magento\CustomerImportExport\Model\Import\AbstractCustomer|PHPUnit_Framework_MockObject_MockObject
      */
     protected function _getModelMock()
     {
@@ -91,7 +91,7 @@ class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
             $customerCollection->addItem(new \Magento\Framework\Object($customer));
         }
 
-        $modelMock = $this->getMockBuilder('Magento\Customer\Model\ImportExport\Import\AbstractCustomer')
+        $modelMock = $this->getMockBuilder('Magento\CustomerImportExport\Model\Import\AbstractCustomer')
             ->disableOriginalConstructor()
             ->setMethods(['_getCustomerCollection', '_validateRowForUpdate', '_validateRowForDelete'])
             ->getMockForAbstractClass();
@@ -185,7 +185,7 @@ class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
     public function testCheckUniqueKey(array $rowData, array $errors, $isValid = false)
     {
         $checkUniqueKey = new \ReflectionMethod(
-            'Magento\Customer\Model\ImportExport\Import\AbstractCustomer',
+            'Magento\CustomerImportExport\Model\Import\AbstractCustomer',
             '_checkUniqueKey'
         );
         $checkUniqueKey->setAccessible(true);
@@ -239,7 +239,7 @@ class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
     {
         // clear array
         $validatedRows = new \ReflectionProperty(
-            'Magento\Customer\Model\ImportExport\Import\AbstractCustomer',
+            'Magento\CustomerImportExport\Model\Import\AbstractCustomer',
             '_validatedRows'
         );
         $validatedRows->setAccessible(true);
@@ -248,7 +248,7 @@ class AbstractCustomerTest extends \PHPUnit_Framework_TestCase
 
         // reset counter
         $entitiesCount = new \ReflectionProperty(
-            'Magento\Customer\Model\ImportExport\Import\AbstractCustomer',
+            'Magento\CustomerImportExport\Model\Import\AbstractCustomer',
             '_processedEntitiesCount'
         );
         $entitiesCount->setAccessible(true);
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
similarity index 97%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
index 34a8a9ec9ea..9bfd80d7822 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/AddressTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php
@@ -22,7 +22,7 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 use Magento\ImportExport\Model\Import\AbstractEntity;
 
@@ -249,7 +249,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     protected function _createCustomerStorageMock()
     {
         $customerStorage = $this->getMock(
-            'Magento\Customer\Model\Resource\ImportExport\Import\Customer\Storage',
+            'Magento\CustomerImportExport\Model\Resource\Import\Customer\Storage',
             array('load'),
             array(),
             '',
@@ -366,7 +366,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
 
         // entity adapter mock
         $modelMock = $this->getMock(
-            'Magento\Customer\Model\ImportExport\Import\Address',
+            'Magento\CustomerImportExport\Model\Import\Address',
             array(
                 'validateRow',
                 '_prepareDataForUpdate',
@@ -399,7 +399,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
         $dataSourceMock->expects($this->at(1))->method('getNextBunch')->will($this->returnValue(null));
 
         $dataSourceModel = new \ReflectionProperty(
-            'Magento\Customer\Model\ImportExport\Import\Address',
+            'Magento\CustomerImportExport\Model\Import\Address',
             '_dataSourceModel'
         );
         $dataSourceModel->setAccessible(true);
@@ -454,7 +454,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
             $this->getMock('Magento\ImportExport\Model\Export\Factory', array(), array(), '', false),
             $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false),
             $this->getMock(
-                'Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory',
+                'Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory',
                 array(),
                 array(),
                 '',
@@ -590,8 +590,8 @@ class AddressTest extends \PHPUnit_Framework_TestCase
      * Test Address::validateRow()
      * with 2 rows with identical PKs in case when add/update behavior is performed
      *
-     * @covers \Magento\Customer\Model\ImportExport\Import\Address::validateRow
-     * @covers \Magento\Customer\Model\ImportExport\Import\Address::_validateRowForUpdate
+     * @covers \Magento\CustomerImportExport\Model\Import\Address::validateRow
+     * @covers \Magento\CustomerImportExport\Model\Import\Address::_validateRowForUpdate
      */
     public function testValidateRowForUpdateDuplicateRows()
     {
@@ -640,7 +640,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     /**
      * Test Address::validateRow() with delete action
      *
-     * @covers \Magento\Customer\Model\ImportExport\Import\Address::validateRow
+     * @covers \Magento\CustomerImportExport\Model\Import\Address::validateRow
      * @dataProvider validateRowForDeleteDataProvider
      *
      * @param array $rowData
@@ -689,7 +689,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase
     /**
      * Test if correct methods are invoked according to different custom behaviours
      *
-     * @covers \Magento\Customer\Model\ImportExport\Import\Address::_importData
+     * @covers \Magento\CustomerImportExport\Model\Import\Address::_importData
      */
     public function testImportDataWithCustomBehaviour()
     {
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
similarity index 98%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
index 0c93e7ee4a1..e4a86f7a45c 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerCompositeTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerCompositeTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 use Magento\Framework\Filesystem\Driver\File;
 use Magento\Framework\Filesystem\File\Read;
@@ -71,7 +71,7 @@ class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
     protected $_resourceHelper;
 
     /**
-     * @var \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory
+     * @var \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory
      */
     protected $_dataFactory;
 
@@ -154,21 +154,21 @@ class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
             false
         );
         $this->_dataFactory = $this->getMock(
-            'Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory',
+            'Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory',
             array(),
             array(),
             '',
             false
         );
         $this->_customerFactory = $this->getMock(
-            'Magento\Customer\Model\ImportExport\Import\CustomerFactory',
+            'Magento\CustomerImportExport\Model\Import\CustomerFactory',
             array(),
             array(),
             '',
             false
         );
         $this->_addressFactory = $this->getMock(
-            'Magento\Customer\Model\ImportExport\Import\AddressFactory',
+            'Magento\CustomerImportExport\Model\Import\AddressFactory',
             array(),
             array(),
             '',
@@ -290,7 +290,7 @@ class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
         $mockedMethods[] = 'getWebsiteId';
 
         $customerEntity = $this->getMock(
-            'Magento\Customer\Model\ImportExport\Import\Customer',
+            'Magento\CustomerImportExport\Model\Import\Customer',
             $mockedMethods,
             array(),
             '',
@@ -325,7 +325,7 @@ class CustomerCompositeTest extends \PHPUnit_Framework_TestCase
         $mockedMethods[] = 'getAttributeCollection';
 
         $addressEntity = $this->getMock(
-            'Magento\Customer\Model\ImportExport\Import\Address',
+            'Magento\CustomerImportExport\Model\Import\Address',
             $mockedMethods,
             array(),
             '',
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
similarity index 96%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
index 24819fc15fb..724a324007d 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/CustomerTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
@@ -23,9 +23,9 @@
  */
 
 /**
- * Test class for \Magento\Customer\Model\ImportExport\Import\Customer
+ * Test class for \Magento\CustomerImportExport\Model\Import\Customer
  */
-namespace Magento\Customer\Model\ImportExport\Import;
+namespace Magento\CustomerImportExport\Model\Import;
 
 class CustomerTest extends \PHPUnit_Framework_TestCase
 {
@@ -95,7 +95,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
     protected function _getModelMockForTestImportDataWithCustomBehaviour()
     {
         // entity adapter mock
-        $modelMock = $this->getMockBuilder('Magento\Customer\Model\ImportExport\Import\Customer')
+        $modelMock = $this->getMockBuilder('Magento\CustomerImportExport\Model\Import\Customer')
             ->disableOriginalConstructor()
             ->setMethods(
                 [
@@ -129,7 +129,7 @@ class CustomerTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(null));
 
         $property = new \ReflectionProperty(
-            'Magento\Customer\Model\ImportExport\Import\Customer',
+            'Magento\CustomerImportExport\Model\Import\Customer',
             '_dataSourceModel'
         );
         $property->setAccessible(true);
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_prepare_row_for_db.csv b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_prepare_row_for_db.csv
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/customer_composite_prepare_row_for_db.csv
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/customer_composite_prepare_row_for_db.csv
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_empty_email.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_empty_email.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_empty_email.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_empty_email.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_empty_website.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_empty_website.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_empty_website.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_empty_website.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_invalid_email.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_invalid_email.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_invalid_email.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_invalid_email.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_invalid_website.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_invalid_website.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_invalid_website.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_invalid_website.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_no_email.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_no_email.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_no_email.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_no_email.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_no_website.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_no_website.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_no_website.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_no_website.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_valid.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_valid.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_abstract_valid.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_abstract_valid.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_address_not_found.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_address_not_found.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_address_not_found.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_address_not_found.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_empty_address_id.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_empty_address_id.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_empty_address_id.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_empty_address_id.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_no_customer.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_no_customer.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_no_customer.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_no_customer.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_valid.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_valid.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_delete_valid.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_delete_valid.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_absent_required_attribute.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_absent_required_attribute.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_absent_required_attribute.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_absent_required_attribute.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_empty_address_id.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_empty_address_id.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_empty_address_id.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_empty_address_id.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_invalid_region.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_invalid_region.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_invalid_region.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_invalid_region.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_no_customer.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_no_customer.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_no_customer.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_no_customer.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_valid.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_valid.php
similarity index 100%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/ImportExport/Import/_files/row_data_address_update_valid.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Import/_files/row_data_address_update_valid.php
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/Customer/StorageTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/Customer/StorageTest.php
similarity index 98%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/Customer/StorageTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/Customer/StorageTest.php
index ec0f0d89f0b..2edd4d80c51 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/Customer/StorageTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/Customer/StorageTest.php
@@ -21,7 +21,7 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Customer\Model\Resource\ImportExport\Import\Customer;
+namespace Magento\CustomerImportExport\Model\Resource\Import\Customer;
 
 class StorageTest extends \PHPUnit_Framework_TestCase
 {
diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/DataTest.php b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/DataTest.php
similarity index 93%
rename from dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/DataTest.php
rename to dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/DataTest.php
index 8d26ec77882..84ea99b371f 100644
--- a/dev/tests/unit/testsuite/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/DataTest.php
+++ b/dev/tests/unit/testsuite/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/DataTest.php
@@ -23,12 +23,12 @@
  */
 
 /**
- * Test class for \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\Data
+ * Test class for \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\Data
  */
-namespace Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite;
+namespace Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite;
 
-use Magento\Customer\Model\ImportExport\Import\Address;
-use Magento\Customer\Model\ImportExport\Import\CustomerComposite;
+use Magento\CustomerImportExport\Model\Import\Address;
+use Magento\CustomerImportExport\Model\Import\CustomerComposite;
 
 class DataTest extends \PHPUnit_Framework_TestCase
 {
@@ -100,9 +100,9 @@ class DataTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\Data::getNextBunch
-     * @covers \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\Data::_prepareRow
-     * @covers \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\Data::_prepareAddressRowData
+     * @covers \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\Data::getNextBunch
+     * @covers \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\Data::_prepareRow
+     * @covers \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\Data::_prepareAddressRowData
      *
      * @dataProvider getNextBunchDataProvider
      * @param string $entityType
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/AreaListTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/AreaListTest.php
index d2678ac73c8..e3a4a94ec6e 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/App/AreaListTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/AreaListTest.php
@@ -61,12 +61,12 @@ class AreaListTest extends \PHPUnit_Framework_TestCase
         $this->_resolverFactory->expects(
             $this->any()
         )->method(
-            'create'
-        )->with(
-            'testValue'
-        )->will(
-            $this->returnValue($resolverMock)
-        );
+                'create'
+            )->with(
+                'testValue'
+            )->will(
+                $this->returnValue($resolverMock)
+            );
 
         $actual = $this->_model->getCodeByFrontName('testFrontName');
         $this->assertEquals($expected, $actual);
@@ -78,7 +78,7 @@ class AreaListTest extends \PHPUnit_Framework_TestCase
         $this->_model = new \Magento\Framework\App\AreaList(
             $this->objectManagerMock,
             $this->_resolverFactory,
-            array('testArea'=>array('frontName' => 'testFrontName')),
+            array('testArea' => array('frontName' => 'testFrontName')),
             $expected
         );
 
@@ -115,12 +115,54 @@ class AreaListTest extends \PHPUnit_Framework_TestCase
 
     public function testGetCodes()
     {
+        $areas = array('area1' => 'value1', 'area2' => 'value2');
         $this->_model = new \Magento\Framework\App\AreaList(
-            $this->objectManagerMock, $this->_resolverFactory, array('area1' => 'value1', 'area2' => 'value2'), ''
+            $this->objectManagerMock, $this->_resolverFactory, $areas, ''
         );
 
-        $expected = array(0 => 'area1', 1 => 'area2');
+        $expected = array_keys($areas);
         $actual = $this->_model->getCodes();
         $this->assertEquals($expected, $actual);
     }
+
+    public function testGetDefaultRouter()
+    {
+        $areas = array('area1' => ['router' => 'value1'], 'area2' => 'value2');
+        $this->_model = new \Magento\Framework\App\AreaList(
+            $this->objectManagerMock, $this->_resolverFactory, $areas, ''
+        );
+
+        $this->assertEquals($this->_model->getDefaultRouter('area1'), $areas['area1']['router']);
+        $this->assertNull($this->_model->getDefaultRouter('area2'));
+    }
+
+    public function testGetArea()
+    {
+        /** @var \Magento\Framework\ObjectManager $objectManagerMock */
+        $objectManagerMock = $this->getObjectManagerMockGetArea();
+        $areas = array('area1' => ['router' => 'value1'], 'area2' => 'value2');
+        $this->_model = new AreaList(
+            $objectManagerMock, $this->_resolverFactory, $areas, ''
+        );
+
+        $this->assertEquals($this->_model->getArea('testArea'), 'ok');
+    }
+
+    /**
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function getObjectManagerMockGetArea()
+    {
+        $objectManagerMock = $this->getMock('Magento\Framework\ObjectManager', [], [], '', false);
+        $objectManagerMock
+            ->expects($this->any())
+            ->method('create')
+            ->with(
+                $this->equalTo('Magento\Framework\App\AreaInterface'),
+                $this->equalTo(array('areaCode' => 'testArea'))
+            )
+            ->will($this->returnValue('ok'));
+
+        return $objectManagerMock;
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Config/ElementTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Config/ElementTest.php
similarity index 60%
rename from dev/tests/integration/testsuite/Magento/Framework/App/Config/ElementTest.php
rename to dev/tests/unit/testsuite/Magento/Framework/App/Config/ElementTest.php
index 2db0315f7e4..c54071855b1 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/App/Config/ElementTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Config/ElementTest.php
@@ -28,55 +28,31 @@ class ElementTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \Magento\Framework\App\Config\Element
      */
-    protected $_model;
+    protected $model;
 
     protected function setUp()
     {
-        $xml = <<<XML
-<?xml version="1.0"?>
-<root>
-    <is_test>
-        <value_key>value</value_key>
-        <value_sensitive_key>vaLue</value_sensitive_key>
-        <false_key>false</false_key>
-        <off_key>off</off_key>
-        <regular_cdata><![CDATA[value]]></regular_cdata>
-        <empty_cdata><![CDATA[]]></empty_cdata>
-        <empty_text></empty_text>
-    </is_test>
-    <class_test>
-        <class>Magento\Catalog\Model\Observer</class>
-    </class_test>
-    <model_test>
-        <model>Magento\Catalog\Model\Observer</model>
-    </model_test>
-    <no_classname_test>
-        <none/>
-    </no_classname_test>
-</root>
-XML;
-        /**
-         * @TODO: Need to use ObjectManager instead 'new'.
-         * On this moment we have next bug MAGETWO-4274 which blocker for this key.
-         */
-        $this->_model = new \Magento\Framework\App\Config\Element($xml);
+        $xmlString = file_get_contents(__DIR__ . '/_files/element.xml');
+        $this->model = new \Magento\Framework\App\Config\Element($xmlString);
     }
 
     public function testIs()
     {
-        $element = $this->_model->is_test;
+        /* @var \Magento\Framework\App\Config\Element $element */
+        $element = $this->model->is_test;
         $this->assertTrue($element->is('value_key', 'value'));
         $this->assertTrue($element->is('value_sensitive_key', 'value'));
         $this->assertTrue($element->is('regular_cdata', 'value'));
         $this->assertFalse($element->is('false_key'));
         $this->assertFalse($element->is('empty_cdata'));
         $this->assertFalse($element->is('empty_text'));
+        $this->assertTrue($element->is('on_key'));
     }
 
     public function testGetClassName()
     {
-        $this->assertEquals('Magento\Catalog\Model\Observer', $this->_model->class_test->getClassName());
-        $this->assertEquals('Magento\Catalog\Model\Observer', $this->_model->model_test->getClassName());
-        $this->assertFalse($this->_model->no_classname_test->getClassName());
+        $this->assertEquals('Magento\Catalog\Model\Observer', $this->model->class_test->getClassName());
+        $this->assertEquals('Magento\Catalog\Model\Observer', $this->model->model_test->getClassName());
+        $this->assertFalse($this->model->no_classname_test->getClassName());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Config/ValueTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Config/ValueTest.php
new file mode 100644
index 00000000000..0186dfbfa7b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Config/ValueTest.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\App\Config;
+
+class ValueTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\App\Config\Value
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $eventManager;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $configMock;
+
+    /**
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->configMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
+        $this->eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface');
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->model = $objectManager->getObject(
+            'Magento\Framework\App\Config\Value',
+            [
+                'config' => $this->configMock,
+                'eventDispatcher' => $this->eventManager,
+            ]
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testGetOldValue()
+    {
+        $this->configMock->expects(
+            $this->once()
+        )->method(
+            'getValue'
+        )->with(
+            null,
+            'default'
+        )->will(
+            $this->returnValue('old_value')
+        );
+
+        $this->assertEquals('old_value', $this->model->getOldValue());
+    }
+
+    /**
+     * @param string $oldValue
+     * @param string $value
+     * @param bool $result
+     * @dataProvider dataIsValueChanged
+     */
+    public function testIsValueChanged($oldValue, $value, $result)
+    {
+        $this->configMock->expects(
+            $this->once()
+        )->method(
+            'getValue'
+        )->with(
+            null,
+            'default'
+        )->will(
+            $this->returnValue($oldValue)
+        );
+
+        $this->model->setValue($value);
+
+        $this->assertEquals($result, $this->model->isValueChanged());
+    }
+
+    /**
+     * @return array
+     */
+    public function dataIsValueChanged()
+    {
+        return [
+            ['value', 'value', false],
+            ['value', 'new_value', true],
+        ];
+    }
+
+    /**
+     * @return void
+     */
+    public function testAfterLoad()
+    {
+        $this->eventManager->expects(
+            $this->at(0)
+        )->method(
+            'dispatch'
+        )->with(
+            'model_load_after',
+            ['object' => $this->model]
+        );
+        $this->eventManager->expects(
+            $this->at(1)
+        )->method(
+            'dispatch'
+        )->with(
+            'config_data_load_after',
+            [
+                'data_object' => $this->model,
+                'config_data' => $this->model,
+            ]
+        );
+
+        $this->model->afterLoad();
+    }
+
+    /**
+     * @param mixed $fieldsetData
+     * @param string $key
+     * @param string $result
+     * @dataProvider dataProviderGetFieldsetDataValue
+     * @return void
+     */
+    public function testGetFieldsetDataValue($fieldsetData, $key, $result)
+    {
+        $this->model->setData('fieldset_data', $fieldsetData);
+        $this->assertEquals($result, $this->model->getFieldsetDataValue($key));
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderGetFieldsetDataValue()
+    {
+        return [
+            [
+                ['key' => 'value'],
+                'key',
+                'value',
+            ],
+            [
+                ['key' => 'value'],
+                'none',
+                null,
+            ],
+            [
+                'value',
+                'key',
+                null,
+            ],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Config/_files/element.xml b/dev/tests/unit/testsuite/Magento/Framework/App/Config/_files/element.xml
new file mode 100644
index 00000000000..f93d61d1f03
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Config/_files/element.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<root>
+    <is_test>
+        <value_key>value</value_key>
+        <value_sensitive_key>vaLue</value_sensitive_key>
+        <false_key>false</false_key>
+        <off_key>off</off_key>
+        <on_key>on</on_key>
+        <regular_cdata><![CDATA[value]]></regular_cdata>
+        <empty_cdata><![CDATA[]]></empty_cdata>
+        <empty_text></empty_text>
+    </is_test>
+    <class_test>
+        <class>Magento\Catalog\Model\Observer</class>
+    </class_test>
+    <model_test>
+        <model>Magento\Catalog\Model\Observer</model>
+    </model_test>
+    <no_classname_test>
+        <none/>
+    </no_classname_test>
+</root>
diff --git a/lib/internal/Magento/Framework/Locale/Hierarchy/Config.php b/dev/tests/unit/testsuite/Magento/Framework/App/DefaultPath/DefaultPathTest.php
similarity index 57%
rename from lib/internal/Magento/Framework/Locale/Hierarchy/Config.php
rename to dev/tests/unit/testsuite/Magento/Framework/App/DefaultPath/DefaultPathTest.php
index b353920a325..1a5a4fefb91 100644
--- a/lib/internal/Magento/Framework/Locale/Hierarchy/Config.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/DefaultPath/DefaultPathTest.php
@@ -1,7 +1,5 @@
 <?php
 /**
- * Locales hierarchy configuration model
- *
  * Magento
  *
  * NOTICE OF LICENSE
@@ -23,30 +21,38 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Framework\Locale\Hierarchy;
+namespace Magento\Framework\App\DefaultPath;
 
-class Config extends \Magento\Framework\Config\Data
+class DefaultPathTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @param \Magento\Framework\Config\ReaderInterface $reader
-     * @param \Magento\Framework\Config\CacheInterface $cache
-     * @param string $cacheId
+     * @param array $parts
+     * @param string $code
+     * @param string $result
+     * @dataProvider dataProviderGetPart
      */
-    public function __construct(
-        \Magento\Framework\Config\ReaderInterface $reader,
-        \Magento\Framework\Config\CacheInterface $cache,
-        $cacheId = 'local_hierarchy_cache'
-    ) {
-        parent::__construct($reader, $cache, $cacheId);
+    public function testGetPart($parts, $code, $result)
+    {
+        $model = new \Magento\Framework\App\DefaultPath\DefaultPath($parts);
+        $this->assertEquals($result, $model->getPart($code));
     }
 
     /**
-     * Get locale hierarchy
-     *
      * @return array
      */
-    public function getHierarchy()
+    public function dataProviderGetPart()
     {
-        return $this->get();
+        return [
+            [
+                ['code' => 'value'],
+                'code',
+                'value',
+            ],
+            [
+                ['code' => 'value'],
+                'other_code',
+                null,
+            ],
+        ];
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/EntryPoint/EntryPointTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/EntryPoint/EntryPointTest.php
index d7d83293e1f..6a743df42d8 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/App/EntryPoint/EntryPointTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/EntryPoint/EntryPointTest.php
@@ -46,25 +46,26 @@ class EntryPointTest extends \PHPUnit_Framework_TestCase
     protected $_rootDir;
 
     /**
-     * @var array()
+     * @return void
      */
-    protected $_parameters;
-
     protected function setUp()
     {
-        $this->_parameters = array('MAGE_MODE' => 'developer');
         $this->_objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
         $this->_responseMock = $this->getMock('Magento\Framework\App\Response\Http', array(), array(), '', false);
         $this->_rootDir = realpath(__DIR__ . '/../../../../../../../');
+    }
+
+    /**
+     * @return void
+     */
+    public function testRunExecutesApplication()
+    {
         $this->_model = new \Magento\Framework\App\EntryPoint\EntryPoint(
             $this->_rootDir,
-            $this->_parameters,
+            array(),
             $this->_objectManagerMock
         );
-    }
 
-    public function testRunExecutesApplication()
-    {
         $applicationName = '\Magento\Framework\App\TestApplication';
         $applicationMock = $this->getMock('\Magento\Framework\AppInterface');
         $applicationMock->expects($this->once())->method('launch')->will($this->returnValue($this->_responseMock));
@@ -81,8 +82,17 @@ class EntryPointTest extends \PHPUnit_Framework_TestCase
         $this->assertNull($this->_model->run($applicationName));
     }
 
-    public function testRunCatchesExceptionThrownByApplication()
+    /**
+     * @return void
+     */
+    public function testRunCatchesExceptionThrownByApplicationDeveloperMode()
     {
+        $this->_model = new \Magento\Framework\App\EntryPoint\EntryPoint(
+            $this->_rootDir,
+            array('MAGE_MODE' => 'developer'),
+            $this->_objectManagerMock
+        );
+
         $applicationName = '\Magento\Framework\App\TestApplication';
         $applicationMock = $this->getMock('\Magento\Framework\AppInterface');
         $applicationMock->expects(
@@ -107,4 +117,68 @@ class EntryPointTest extends \PHPUnit_Framework_TestCase
         $this->assertNull($this->_model->run($applicationName));
         ob_end_clean();
     }
+
+    /**
+     * @return void
+     */
+    public function testRunCatchesExceptionThrownByApplicationNonDeveloperMode()
+    {
+        $this->_model = new \Magento\Framework\App\EntryPoint\EntryPoint(
+            $this->_rootDir,
+            array(),
+            $this->_objectManagerMock
+        );
+
+        $exception = new \Exception('Something went wrong.');
+
+        $applicationName = '\Magento\Framework\App\TestApplication';
+        $applicationMock = $this->getMock('\Magento\Framework\AppInterface');
+        $applicationMock->expects(
+            $this->once()
+        )->method(
+            'launch'
+        )->will(
+            $this->throwException($exception)
+        );
+
+        $loggerMock = $this->getMock(
+            '\Magento\Framework\Logger',
+            array(),
+            array(),
+            '',
+            false
+        );
+        $loggerMock->expects(
+            $this->once()
+        )->method(
+            'logException'
+        )->will(
+            $this->throwException($exception)
+        );
+
+        $this->_objectManagerMock->expects(
+            $this->at(0)
+        )->method(
+            'create'
+        )->with(
+            $applicationName,
+            array()
+        )->will(
+            $this->returnValue($applicationMock)
+        );
+        $this->_objectManagerMock->expects(
+            $this->at(1)
+        )->method(
+            'get'
+        )->with(
+            'Magento\Framework\Logger'
+        )->will(
+            $this->returnValue($loggerMock)
+        );
+
+        // clean output
+        ob_start();
+        $this->assertNull($this->_model->run($applicationName));
+        ob_end_clean();
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
new file mode 100644
index 00000000000..b1b939ae96e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Language/DictionaryTest.php
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\App\Language;
+
+class DictionaryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\App\Language\Dictionary
+     */
+    private $model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $dir;
+
+    protected function setUp()
+    {
+        $this->dir = $this->getMockForAbstractClass('\Magento\Framework\Filesystem\Directory\ReadInterface');
+        $filesystem = $this->getMock('\Magento\Framework\App\Filesystem', [], [], '', false);
+        $filesystem->expects($this->once())
+            ->method('getDirectoryRead')
+            ->with(\Magento\Framework\App\Filesystem::LOCALE_DIR)
+            ->will($this->returnValue($this->dir))
+        ;
+        $this->model = new Dictionary($filesystem);
+    }
+
+    public function testGetDictionary()
+    {
+        $dir = [
+            'Foo/en_AU/language.xml',
+            'Bar/en_GB/language.xml',
+            'Baz/en_GB/language.xml',
+            'Bar/en_US/language.xml'
+        ];
+        $xmlMap = [
+            [
+                $dir[0],
+                null,
+                null,
+                '<?xml version="1.0"?>
+                <language>
+                    <code>en_AU</code>
+                    <vendor>Foo</vendor>
+                    <use vendor="Bar" code="en_GB"/>
+                    <use vendor="Baz" code="en_GB"/>
+                </language>'
+            ],
+            [
+                $dir[1],
+                null,
+                null,
+                '<?xml version="1.0"?>
+                <language>
+                    <code>en_GB</code>
+                    <vendor>Bar</vendor>
+                    <sort_order>100</sort_order>
+                    <use vendor="Bar" code="en_US"/>
+                </language>'
+            ],
+            [
+                $dir[2],
+                null,
+                null,
+                '<?xml version="1.0"?>
+                <language>
+                    <code>en_GB</code>
+                    <vendor>Baz</vendor>
+                    <sort_order>50</sort_order>
+                </language>'
+            ],
+            [
+                $dir[3],
+                null,
+                null,
+                '<?xml version="1.0"?>
+                <language>
+                    <code>en_US</code>
+                    <vendor>Bar</vendor>
+                </language>'
+            ],
+        ];
+        $csvMap = [
+            ['Bar/en_US/*.csv', null, ['Bar/en_US/b.csv', 'Bar/en_US/a.csv']],
+            ['Baz/en_GB/*.csv', null, ['Baz/en_GB/1.csv']],
+            ['Bar/en_GB/*.csv', null, ['Bar/en_GB/1.csv']],
+            ['Foo/en_AU/*.csv', null, ['Foo/en_AU/1.csv', 'Foo/en_AU/2.csv']],
+        ];
+        $dictionaryMap = [
+            ['Bar/en_US/a.csv', $this->getCsvMock([['one', '1'], ['two', '2']])],
+            ['Bar/en_US/b.csv', $this->getCsvMock([['three', '3'], ['four', '4']])],
+            ['Baz/en_GB/1.csv', $this->getCsvMock([['four and 5/10', '4.5']])],
+            ['Bar/en_GB/1.csv', $this->getCsvMock([['four and 75/100', '4.75'], ['four and 5/10', '4.50']])],
+            ['Foo/en_AU/1.csv', $this->getCsvMock([['one', '1.0'], ['five', '5.0']])],
+            ['Foo/en_AU/2.csv', $this->getCsvMock([['six', '6.0']])],
+        ];
+        $this->dir->expects($this->any())->method('search')->will($this->returnValueMap(
+            array_merge([['*/*/language.xml', null, $dir]], $csvMap)
+        ));
+        $this->dir->expects($this->any())->method('readFile')->will($this->returnValueMap($xmlMap));
+        $this->dir->expects($this->any())->method('openFile')->will($this->returnValueMap($dictionaryMap));
+        $result = $this->model->getDictionary('en_AU');
+        $this->assertSame(
+            [
+                'one' => '1.0',
+                'two' => '2',
+                'three' => '3',
+                'four' => '4',
+                'four and 5/10' => '4.50',
+                'four and 75/100' => '4.75',
+                'five' => '5.0',
+                'six' => '6.0'
+            ],
+            $result
+        );
+    }
+
+    /**
+     * Imitate a CSV-file read operation through "App filesystem" interface
+     *
+     * @param array $data
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getCsvMock($data)
+    {
+        $file = $this->getMockForAbstractClass('Magento\Framework\Filesystem\File\ReadInterface');
+        for ($i = 0; $i < count($data); $i++) {
+            $file->expects($this->at($i))->method('readCsv')->will($this->returnValue($data[$i]));
+        }
+        $file->expects($this->at($i))->method('readCsv')->will($this->returnValue(false));
+        return $file;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Resource/ConnectionFactoryTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Resource/ConnectionFactoryTest.php
new file mode 100644
index 00000000000..0a6efa0f037
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Resource/ConnectionFactoryTest.php
@@ -0,0 +1,199 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\App\Resource;
+
+class ConnectionFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\App\Resource\ConnectionFactory
+     */
+    protected $model;
+
+    /**
+     * @var \Magento\Framework\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $objectManager;
+
+    /**
+     * @var \Magento\Framework\App\Arguments|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $localConfig;
+
+    protected function setUp()
+    {
+        $this->objectManager = $this->getMock(
+            '\Magento\Framework\ObjectManager',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->localConfig = $this->getMock(
+            '\Magento\Framework\App\Arguments',
+            [],
+            [],
+            '',
+            false
+        );
+
+        $this->model = new \Magento\Framework\App\Resource\ConnectionFactory(
+            $this->objectManager,
+            $this->localConfig
+        );
+    }
+
+    /**
+     * @param array $config
+     * @dataProvider dataProviderCreateNoActiveConfig
+     */
+    public function testCreateNoActiveConfig($config)
+    {
+        $this->localConfig->expects(
+            $this->once()
+        )->method(
+            'getConnection'
+        )->with(
+            'connection_name'
+        )->will(
+            $this->returnValue($config)
+        );
+
+        $this->assertNull($this->model->create('connection_name'));
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderCreateNoActiveConfig()
+    {
+        return [
+            [null, null],
+            [['value'], null],
+            [['active' => 0], null],
+        ];
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Adapter is not set for connection "connection_name"
+     */
+    public function testCreateNoAdapter()
+    {
+        $config = [
+            'active' => 1,
+        ];
+
+        $this->localConfig->expects(
+            $this->once()
+        )->method(
+            'getConnection'
+        )->with(
+            'connection_name'
+        )->will(
+            $this->returnValue($config)
+        );
+
+        $this->model->create('connection_name');
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Trying to create wrong connection adapter
+     */
+    public function testCreateNoWrongAdapter()
+    {
+        $config = [
+            'active' => 1,
+            'adapter' => 'StdClass',
+        ];
+
+        $this->localConfig->expects(
+            $this->once()
+        )->method(
+            'getConnection'
+        )->with(
+            'connection_name'
+        )->will(
+            $this->returnValue($config)
+        );
+
+        $adapterMock = $this->getMock('StdClass');
+
+        $this->objectManager->expects(
+            $this->once()
+        )->method(
+            'create'
+        )->with(
+            'StdClass',
+            $config
+        )->will(
+            $this->returnValue($adapterMock)
+        );
+
+        $this->model->create('connection_name');
+    }
+
+    public function testCreate()
+    {
+        $config = [
+            'active' => 1,
+            'adapter' => 'Magento\Framework\App\Resource\ConnectionAdapterInterface',
+        ];
+
+        $this->localConfig->expects(
+            $this->once()
+        )->method(
+            'getConnection'
+        )->with(
+            'connection_name'
+        )->will(
+            $this->returnValue($config)
+        );
+
+        $adapterMock = $this->getMock('Magento\Framework\App\Resource\ConnectionAdapterInterface');
+
+        $this->objectManager->expects(
+            $this->once()
+        )->method(
+            'create'
+        )->with(
+            'Magento\Framework\App\Resource\ConnectionAdapterInterface',
+            $config
+        )->will(
+            $this->returnValue($adapterMock)
+        );
+
+        $connectionMock = $this->getMock('Magento\Framework\DB\Adapter\AdapterInterface');
+
+        $adapterMock->expects(
+            $this->once()
+        )->method(
+            'getConnection'
+        )->will(
+            $this->returnValue($connectionMock)
+        );
+
+        $this->assertEquals($connectionMock, $this->model->create('connection_name'));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/App/Route/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/App/Route/ConfigTest.php
index c9e8e5c4f4f..fbe19601045 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/App/Route/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/App/Route/ConfigTest.php
@@ -96,9 +96,90 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         )->will(
             $this->returnValue(serialize(array('routerCode' => ['frontName' => 'routerName'])))
         );
+
+        $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName'));
+
+        // check internal caching in $this->_routes array
         $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName'));
     }
 
+    public function testGetRouteByFrontNameNoRoutes()
+    {
+        $this->_cacheMock->expects(
+            $this->once()
+        )->method(
+            'load'
+        )->with(
+            'areaCode::RoutesConfig'
+        )->will(
+            $this->returnValue(serialize(array()))
+        );
+
+        $this->assertFalse($this->_config->getRouteByFrontName('routerName'));
+
+        // check caching in $this->_routes array
+        $this->assertFalse($this->_config->getRouteByFrontName('routerName'));
+    }
+
+    public function testGetRouteByFrontNameNoCache()
+    {
+        $this->_cacheMock->expects(
+            $this->once()
+        )->method(
+            'load'
+        )->with(
+            'scope::RoutesConfig'
+        )->will(
+            $this->returnValue(serialize(false))
+        );
+
+        $routes = array(
+            'routerCode' => array(
+                'frontName' => 'routerName'
+            ),
+        );
+
+        $routers = array(
+            'default_router' => array(
+                'routes' => $routes,
+            ),
+        );
+
+        $this->_readerMock->expects(
+            $this->once()
+        )->method(
+            'read'
+        )->with(
+            'scope'
+        )->will(
+            $this->returnValue($routers)
+        );
+
+        $this->_areaList->expects(
+            $this->once()
+        )->method(
+            'getDefaultRouter'
+        )->with(
+            'scope'
+        )->will(
+            $this->returnValue('default_router')
+        );
+
+        $this->_cacheMock->expects(
+            $this->once()
+        )->method(
+            'save'
+        )->with(
+            serialize($routes),
+            'scope::RoutesConfig'
+        );
+
+        $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName', 'scope'));
+
+        // check caching in $this->_routes array
+        $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName', 'scope'));
+    }
+
     public function testGetModulesByFrontName()
     {
         $this->_cacheMock->expects(
diff --git a/dev/tests/unit/testsuite/Magento/Framework/ArchiveTest.php b/dev/tests/unit/testsuite/Magento/Framework/ArchiveTest.php
index b45838ec361..7c0b7799b33 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/ArchiveTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/ArchiveTest.php
@@ -139,11 +139,15 @@ class ArchiveTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @dataProvider destinationProvider
      * @param string $destinationFile
+     * @param string $extensionRequired
+     * @dataProvider destinationProvider
      */
-    public function testPackUnpackGzBz($destinationFile)
+    public function testPackUnpackGzBz($destinationFile, $extensionRequired)
     {
+        if ($extensionRequired && !extension_loaded($extensionRequired)) {
+            $this->markTestSkipped("The extension '{$extensionRequired}' is not enabled.");
+        }
         $this->packed = $this->archive->pack($this->sourceFilePath, $this->destinationDir . $destinationFile);
 
         $this->assertFileExists($this->packed);
@@ -158,21 +162,25 @@ class ArchiveTest extends \PHPUnit_Framework_TestCase
     public function destinationProvider()
     {
         return [
-            ['archive.gz', false],
-            ['archive.gzip', false],
-            ['archive.bz', false],
-            ['archive.bzip', false],
-            ['archive.bzip2', false],
-            ['archive.bz2', false]
+            ['archive.gz', 'zlib'],
+            ['archive.gzip', 'zlib'],
+            ['archive.bz', 'bz2'],
+            ['archive.bzip', 'bz2'],
+            ['archive.bzip2', 'bz2'],
+            ['archive.bz2', 'bz2']
         ];
     }
 
     /**
-     * @dataProvider tarProvider
      * @param string $destinationFile
+     * @param string $extensionRequired
+     * @dataProvider tarProvider
      */
-    public function testPackUnpackTar($destinationFile)
+    public function testPackUnpackTar($destinationFile, $extensionRequired)
     {
+        if ($extensionRequired && !extension_loaded($extensionRequired)) {
+            $this->markTestSkipped("The extension '{$extensionRequired}' is not enabled.");
+        }
         $this->packed = $this->archive->pack($this->sourceFilePath, $this->destinationDir . $destinationFile);
 
         $this->assertFileExists($this->packed);
@@ -187,11 +195,15 @@ class ArchiveTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @dataProvider tarProvider
      * @param string $destinationFile
+     * @param string $extensionRequired
+     * @dataProvider tarProvider
      */
-    public function testExtract($destinationFile)
+    public function testExtract($destinationFile, $extensionRequired)
     {
+        if ($extensionRequired && !extension_loaded($extensionRequired)) {
+            $this->markTestSkipped("The extension '{$extensionRequired}' is not enabled.");
+        }
         $this->packed = $this->archive->pack($this->sourceFilePath, $this->destinationDir . $destinationFile);
 
         $this->assertFileExists($this->packed);
@@ -207,13 +219,13 @@ class ArchiveTest extends \PHPUnit_Framework_TestCase
     public function tarProvider()
     {
         return [
-            ['archive.tar', true],
-            ['archive.tgz', false],
-            ['archive.tgzip', false],
-            ['archive.tbz', false],
-            ['archive.tbzip', false],
-            ['archive.tbz2', false],
-            ['archive.tbzip2', false]
+            ['archive.tar', ''],
+            ['archive.tgz', 'zlib'],
+            ['archive.tgzip', 'zlib'],
+            ['archive.tbz', 'bz2'],
+            ['archive.tbzip', 'bz2'],
+            ['archive.tbz2', 'bz2'],
+            ['archive.tbzip2', 'bz2']
         ];
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/ThemeTest.php b/dev/tests/unit/testsuite/Magento/Framework/Config/ThemeTest.php
index 54440013458..0f1c172628d 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/ThemeTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/ThemeTest.php
@@ -104,25 +104,25 @@ class ThemeTest extends \PHPUnit_Framework_TestCase
             array(
                 'default_default',
                 array(array(
-                    'version' => '2.0.0.9',
+                    'version' => '0.1.0',
                     'media' => array('preview_image' => 'media/default_default.jpg'),
                 ))),
             array(
                 'default_test',
                 array(array(
-                    'version' => '2.1.0.0',
+                    'version' => '0.1.1',
                     'media' => array('preview_image' => ''),
                 ))),
             array(
                 'default_test2',
                 array(array(
-                    'version' => '2.0.0.0',
+                    'version' => '0.1.2',
                     'media' => array('preview_image' => ''),
                 ))),
             array(
                 'test_default',
                 array(array(
-                    'version' => '2.0.1.0',
+                    'version' => '0.1.3',
                     'media' => array('preview_image' => 'media/test_default.jpg'),
                 ))),
         );
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_default/theme.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_default/theme.xml
index e58d5ab9ed5..d831d10387c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_default/theme.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_default/theme.xml
@@ -25,7 +25,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.9</version>
+    <version>0.1.0</version>
     <media>
         <preview_image>media/default_default.jpg</preview_image>
     </media>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test/theme.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test/theme.xml
index 7da52cfa616..bcaa741dfdc 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test/theme.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test/theme.xml
@@ -25,7 +25,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test</title>
-    <version>2.1.0.0</version>
+    <version>0.1.1</version>
     <parent>default_default</parent>
     <media>
         <preview_image />
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test2/theme.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test2/theme.xml
index 26e805a5b10..0852a37044e 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test2/theme.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/default_test2/theme.xml
@@ -25,6 +25,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Test2</title>
-    <version>2.0.0.0</version>
+    <version>0.1.2</version>
     <parent>default_test</parent>
 </theme>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_default/theme.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_default/theme.xml
index ed07c07be39..b6b27ae3d13 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_default/theme.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_default/theme.xml
@@ -25,7 +25,7 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.1.0</version>
+    <version>0.1.3</version>
     <media>
         <preview_image>media/test_default.jpg</preview_image>
     </media>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_external_package_descendant/theme.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_external_package_descendant/theme.xml
index 677eca6885b..1c21461c341 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_external_package_descendant/theme.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/area/test_external_package_descendant/theme.xml
@@ -25,6 +25,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>0.1.4</version>
     <parent>default_test2</parent>
 </theme>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/theme_invalid.xml b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/theme_invalid.xml
index 17cfdbc14a9..de051a43888 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Config/_files/theme_invalid.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Config/_files/theme_invalid.xml
@@ -25,6 +25,6 @@
 -->
 <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd">
     <title>Default</title>
-    <version>2.0.0.0</version>
+    <version>2.0.0</version>
     <parent>some_theme</parent>
 </theme>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Convert/ExcelTest.php b/dev/tests/unit/testsuite/Magento/Framework/Convert/ExcelTest.php
index 05584dbf299..f7569a5f9b8 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Convert/ExcelTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Convert/ExcelTest.php
@@ -35,18 +35,21 @@ class ExcelTest extends \PHPUnit_Framework_TestCase
      * @var array
      */
     private $_testData = array(
-        array('ID', 'Name', 'Email', 'Group', 'Telephone', 'ZIP', 'Country', 'State/Province'),
-        array(1, 'Jon Doe', 'jon.doe@magento.com', 'General', '310-111-1111', 90232, 'United States', 'California')
+        array('ID', 'Name', 'Email', 'Group', 'Telephone', '+Telephone', 'ZIP', '0ZIP', 'Country', 'State/Province'),
+        array(
+            1, 'Jon Doe', 'jon.doe@magento.com', 'General', '310-111-1111', '+310-111-1111', 90232, '090232',
+            'United States', 'California'
+        )
     );
 
     protected $_testHeader = array(
-        'HeaderID', 'HeaderName', 'HeaderEmail', 'HeaderGroup', 'HeaderPhone', 'HeaderZIP',
-        'HeaderCountry', 'HeaderRegion',
+        'HeaderID', 'HeaderName', 'HeaderEmail', 'HeaderGroup', 'HeaderPhone', 'Header+Phone',
+        'HeaderZIP', 'Header0ZIP', 'HeaderCountry', 'HeaderRegion',
     );
 
     protected $_testFooter = array(
-        'FooterID', 'FooterName', 'FooterEmail', 'FooterGroup', 'FooterPhone', 'FooterZIP',
-        'FooterCountry', 'FooterRegion',
+        'FooterID', 'FooterName', 'FooterEmail', 'FooterGroup', 'FooterPhone', 'Footer+Phone',
+        'FooterZIP', 'Footer0ZIP', 'FooterCountry', 'FooterRegion',
     );
 
     /**
@@ -56,7 +59,7 @@ class ExcelTest extends \PHPUnit_Framework_TestCase
      */
     protected function _getSampleOutputFile()
     {
-        return __DIR__ . '/_files/output.txt';
+        return __DIR__ . '/_files/sample.xml';
     }
 
     /**
@@ -85,8 +88,10 @@ class ExcelTest extends \PHPUnit_Framework_TestCase
         $convert = new \Magento\Framework\Convert\Excel(new \ArrayIterator($this->_testData));
         $convert->setDataHeader($this->_testHeader);
         $convert->setDataFooter($this->_testFooter);
-        $isEqual = (file_get_contents($this->_getSampleOutputFile()) == $convert->convert());
-        $this->assertTrue($isEqual, 'Failed asserting that data is the same.');
+        $this->assertXmlStringEqualsXmlString(
+            file_get_contents($this->_getSampleOutputFile()),
+            $convert->convert()
+        );
     }
 
     /**
@@ -149,8 +154,10 @@ class ExcelTest extends \PHPUnit_Framework_TestCase
     public function testWrite()
     {
         $file = $this->_writeFile();
-        $isEqual = file_get_contents($file) == file_get_contents($this->_getSampleOutputFile());
-        $this->assertTrue($isEqual, 'Failed asserting that data from files is the same.');
+        $this->assertXmlStringEqualsXmlString(
+            file_get_contents($this->_getSampleOutputFile()),
+            file_get_contents($file)
+        );
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/output.txt b/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/output.txt
deleted file mode 100644
index 5f977525d48..00000000000
--- a/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/output.txt
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet"><OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"></OfficeDocumentSettings><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"></ExcelWorkbook><Worksheet ss:Name="Sheet 1"><Table><Row><Cell><Data ss:Type="String">HeaderID</Data></Cell><Cell><Data ss:Type="String">HeaderName</Data></Cell><Cell><Data ss:Type="String">HeaderEmail</Data></Cell><Cell><Data ss:Type="String">HeaderGroup</Data></Cell><Cell><Data ss:Type="String">HeaderPhone</Data></Cell><Cell><Data ss:Type="String">HeaderZIP</Data></Cell><Cell><Data ss:Type="String">HeaderCountry</Data></Cell><Cell><Data ss:Type="String">HeaderRegion</Data></Cell></Row><Row><Cell><Data ss:Type="String">ID</Data></Cell><Cell><Data ss:Type="String">Name</Data></Cell><Cell><Data ss:Type="String">Email</Data></Cell><Cell><Data ss:Type="String">Group</Data></Cell><Cell><Data ss:Type="String">Telephone</Data></Cell><Cell><Data ss:Type="String">ZIP</Data></Cell><Cell><Data ss:Type="String">Country</Data></Cell><Cell><Data ss:Type="String">State/Province</Data></Cell></Row><Row><Cell><Data ss:Type="Number">1</Data></Cell><Cell><Data ss:Type="String">Jon Doe</Data></Cell><Cell><Data ss:Type="String">jon.doe@magento.com</Data></Cell><Cell><Data ss:Type="String">General</Data></Cell><Cell><Data ss:Type="String">310-111-1111</Data></Cell><Cell><Data ss:Type="Number">90232</Data></Cell><Cell><Data ss:Type="String">United States</Data></Cell><Cell><Data ss:Type="String">California</Data></Cell></Row><Row><Cell><Data ss:Type="String">FooterID</Data></Cell><Cell><Data ss:Type="String">FooterName</Data></Cell><Cell><Data ss:Type="String">FooterEmail</Data></Cell><Cell><Data ss:Type="String">FooterGroup</Data></Cell><Cell><Data ss:Type="String">FooterPhone</Data></Cell><Cell><Data ss:Type="String">FooterZIP</Data></Cell><Cell><Data ss:Type="String">FooterCountry</Data></Cell><Cell><Data ss:Type="String">FooterRegion</Data></Cell></Row></Table></Worksheet></Workbook>
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/sample.xml b/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/sample.xml
new file mode 100644
index 00000000000..9c8f86ce78f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Convert/_files/sample.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE_AFL.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
+ */
+-->
+<?mso-application progid="Excel.Sheet"?>
+<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:x="urn:schemas-microsoft-com:office:excel"
+    xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml"
+    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
+    xmlns:o="urn:schemas-microsoft-com:office:office"
+    xmlns:html="http://www.w3.org/TR/REC-html40"
+    xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet"
+>
+    <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"></OfficeDocumentSettings>
+    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"></ExcelWorkbook>
+    <Worksheet ss:Name="Sheet 1">
+        <Table>
+            <Row>
+                <Cell><Data ss:Type="String">HeaderID</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderName</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderEmail</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderGroup</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderPhone</Data></Cell>
+                <Cell><Data ss:Type="String">Header+Phone</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderZIP</Data></Cell>
+                <Cell><Data ss:Type="String">Header0ZIP</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderCountry</Data></Cell>
+                <Cell><Data ss:Type="String">HeaderRegion</Data></Cell>
+            </Row>
+            <Row>
+                <Cell><Data ss:Type="String">ID</Data></Cell>
+                <Cell><Data ss:Type="String">Name</Data></Cell>
+                <Cell><Data ss:Type="String">Email</Data></Cell>
+                <Cell><Data ss:Type="String">Group</Data></Cell>
+                <Cell><Data ss:Type="String">Telephone</Data></Cell>
+                <Cell><Data ss:Type="String">+Telephone</Data></Cell>
+                <Cell><Data ss:Type="String">ZIP</Data></Cell>
+                <Cell><Data ss:Type="String">0ZIP</Data></Cell>
+                <Cell><Data ss:Type="String">Country</Data></Cell>
+                <Cell><Data ss:Type="String">State/Province</Data></Cell>
+            </Row>
+            <Row>
+                <Cell><Data ss:Type="Number">1</Data></Cell>
+                <Cell><Data ss:Type="String">Jon Doe</Data></Cell>
+                <Cell><Data ss:Type="String">jon.doe@magento.com</Data></Cell>
+                <Cell><Data ss:Type="String">General</Data></Cell>
+                <Cell><Data ss:Type="String">310-111-1111</Data></Cell>
+                <Cell><Data ss:Type="String">+310-111-1111</Data></Cell>
+                <Cell><Data ss:Type="Number">90232</Data></Cell>
+                <Cell><Data ss:Type="String">090232</Data></Cell>
+                <Cell><Data ss:Type="String">United States</Data></Cell>
+                <Cell><Data ss:Type="String">California</Data></Cell>
+            </Row>
+            <Row>
+                <Cell><Data ss:Type="String">FooterID</Data></Cell>
+                <Cell><Data ss:Type="String">FooterName</Data></Cell>
+                <Cell><Data ss:Type="String">FooterEmail</Data></Cell>
+                <Cell><Data ss:Type="String">FooterGroup</Data></Cell>
+                <Cell><Data ss:Type="String">FooterPhone</Data></Cell>
+                <Cell><Data ss:Type="String">Footer+Phone</Data></Cell>
+                <Cell><Data ss:Type="String">FooterZIP</Data></Cell>
+                <Cell><Data ss:Type="String">Footer0ZIP</Data></Cell>
+                <Cell><Data ss:Type="String">FooterCountry</Data></Cell>
+                <Cell><Data ss:Type="String">FooterRegion</Data></Cell>
+            </Row>
+        </Table>
+    </Worksheet>
+</Workbook>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php b/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
new file mode 100644
index 00000000000..c11e537bd33
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/File/CsvTest.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+/**
+ * Test class for \Magento\Framework\File\Csv.
+ */
+namespace Magento\Framework\File;
+
+class CsvTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Csv model
+     *
+     * @var \Magento\Framework\File\Csv
+     */
+    protected $_model;
+
+    protected function setUp()
+    {
+        $this->_model = new \Magento\Framework\File\Csv();
+    }
+
+    protected function tearDown()
+    {
+        unset($this->_model);
+    }
+
+    public function testSetLineLength()
+    {
+        $expected = 4;
+        $this->_model->setLineLength($expected);
+        $lineLengthProperty = new \ReflectionProperty(
+            'Magento\Framework\File\Csv', '_lineLength'
+        );
+        $lineLengthProperty->setAccessible(true);
+        $actual = $lineLengthProperty->getValue($this->_model);
+        $this->assertEquals($expected, $actual);
+    }
+
+    public function testSetDelimiter()
+    {
+        $this->assertInstanceOf('\Magento\Framework\File\Csv', $this->_model->setDelimiter(','));
+    }
+
+    public function testSetEnclosure()
+    {
+        $this->assertInstanceOf('\Magento\Framework\File\Csv', $this->_model->setEnclosure('"'));
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage File "FileName" do not exists
+     */
+    public function testGetDataFileNonExistent()
+    {
+        $file = 'FileName';
+        $this->_model->getData($file);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/ArrayFilterTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/ArrayFilterTest.php
new file mode 100644
index 00000000000..17433ee240a
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/ArrayFilterTest.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter;
+
+class ArrayFilterTest extends \PHPUnit_Framework_TestCase
+{
+    public function testFilter()
+    {
+        $arrayFilter = new ArrayFilter();
+
+        /** @var \Zend_Filter_Interface $filterMock */
+        /** This filter should be applied to all fields values */
+        $filterMock = $this->getMock('Zend_Filter_Interface', [], [], '', false);
+        $filterMock->expects($this->exactly(3))->method('filter')->will(
+            $this->returnCallback(
+                function ($input) {
+                    return '(' . $input . ')';
+                }
+            )
+        );
+        $arrayFilter->addFilter($filterMock);
+
+        /** @var \Zend_Filter_Interface $fieldFilterMock */
+        /** This filter should be applied to 'field2' field value only */
+        $fieldFilterMock = $this->getMock('Zend_Filter_Interface', [], [], '', false);
+        $fieldFilterMock->expects($this->exactly(1))->method('filter')->will(
+            $this->returnCallback(
+                function ($input) {
+                    return '[' . $input . ']';
+                }
+            )
+        );
+        $arrayFilter->addFilter($fieldFilterMock, 'field2');
+
+        /** Execute SUT and ensure that array items were filtered correctly */
+        $inputArray = ['field1' => 'value1', 'field2' => 'value2', 'field3' => 'value3'];
+        $expectedOutput = ['field1' => '(value1)', 'field2' => '[(value2)]', 'field3' => '(value3)'];
+        $this->assertEquals($expectedOutput, $arrayFilter->filter($inputArray), 'Array was filtered incorrectly.');
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/Input/MaliciousCodeTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/Input/MaliciousCodeTest.php
new file mode 100644
index 00000000000..00d1b47330e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/Input/MaliciousCodeTest.php
@@ -0,0 +1,157 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter\Input;
+
+class MaliciousCodeTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Framework\Filter\Input\MaliciousCode */
+    protected $filter;
+
+    protected function setUp()
+    {
+        $this->filter = new MaliciousCode();
+        parent::setUp();
+    }
+
+    /**
+     * @param string|string[] $input
+     * @param string|string[] $expectedOutput
+     * @dataProvider filterDataProvider
+     */
+    public function testFilter($input, $expectedOutput)
+    {
+        $this->assertEquals(
+            $expectedOutput,
+            $this->filter->filter($input),
+            'Malicious code is not filtered out correctly.'
+        );
+    }
+
+    public function filterDataProvider()
+    {
+        return [
+            'Comments' => ['Comment /** This is omitted */ is removed', 'Comment  is removed'],
+            'Tabs' => ["Tabs \t\t are removed", 'Tabs  are removed'],
+            'JS' => ['JS JavaScript    : is removed', 'JS  is removed'],
+            'Import' => ['Import @import directive is removed', 'Import  directive is removed'],
+            'JS in styles (array of strings to be filtered)' => [
+                [
+                    '<element style="behavior:url(malicious.example.com)"></element>',
+                    '<img src="test.gif" style="height: expression(compatMode==\'CSS1Compat\'? 200px : 300px")/>'
+                ],
+                [
+                    '<element ></element>',
+                    '<img src="test.gif" />'
+                ]
+            ],
+            'JS attributes (array of strings to be filtered)' => [
+                [
+                    '<element ondblclick="SomeJavaScriptCode">',
+                    '<element onclick="SomeJavaScriptCode">',
+                    '<element onkeydown="SomeJavaScriptCode">',
+                    '<element onkeypress="SomeJavaScriptCode">',
+                    '<element onkeyup="SomeJavaScriptCode">',
+                    '<element onmousedown="SomeJavaScriptCode">',
+                    '<element onmousemove="SomeJavaScriptCode">',
+                    '<element onmouseout="SomeJavaScriptCode">',
+                    '<element onmouseover="SomeJavaScriptCode">',
+                    '<element onmouseup="SomeJavaScriptCode">',
+                    '<element onload="SomeJavaScriptCode">',
+                    '<element onunload="SomeJavaScriptCode">',
+                    '<element onerror="SomeJavaScriptCode" />',
+                ],
+                [
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element >',
+                    '<element />',
+                ],
+            ],
+            'Prohibited tags (array of strings to be filtered)' => [
+                [
+                    'Tag is removed <script>SomeScript</script>',
+                    'Tag is removed <meta>SomeMeta</meta>',
+                    'Tag is removed <link>SomeLink</link>',
+                    'Tag is removed <frame>SomeFrame</frame>',
+                    'Tag is removed <iframe>SomeIFrame</iframe>',
+                ],
+                [
+                    'Tag is removed SomeScript',
+                    'Tag is removed SomeMeta',
+                    'Tag is removed SomeLink',
+                    'Tag is removed SomeFrame',
+                    'Tag is removed SomeIFrame',
+                ],
+            ],
+            'Base64' => [
+                '<img alt="Embedded Image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." />',
+                '<img alt="Embedded Image" />'
+            ]
+        ];
+    }
+
+    /**
+     * Ensure that custom filtration regular expressions are applied.
+     */
+    public function testAddExpression()
+    {
+        $customExpression = '/<\/?(customMalicious).*>/Uis';
+        $this->filter->addExpression($customExpression);
+        $this->assertEquals(
+            /** Tabs should be filtered out along with custom malicious code */
+            'Custom malicious tag is removed customMalicious',
+            $this->filter->filter(
+                "Custom \tmalicious tag\t\t is removed <customMalicious>customMalicious</customMalicious>"
+            ),
+            'Custom filters are not applied correctly.'
+        );
+    }
+
+    /**
+     * Ensure that custom filtration regular expressions replace existing ones.
+     */
+    public function testSetExpression()
+    {
+        $customExpression = '/<\/?(customMalicious).*>/Uis';
+        $this->filter->setExpressions([$customExpression]);
+        $this->assertEquals(
+            /** Tabs should not be filtered out along with custom malicious code */
+            "Custom \tmalicious tag\t\t is removed customMalicious",
+            $this->filter->filter(
+                "Custom \tmalicious tag\t\t is removed <customMalicious>customMalicious</customMalicious>"
+            ),
+            'Native filters should have been replaced with custom ones.'
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/InputTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/InputTest.php
new file mode 100644
index 00000000000..146a717125f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/InputTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter;
+
+class InputTest extends \PHPUnit_Framework_TestCase
+{
+    public function testFilterZendFilterAsObject()
+    {
+        $objectManagerMock = $this->getMock('Magento\Framework\ObjectManager', [], [], '', false);
+        $inputFilter = new Input($objectManagerMock);
+
+        /** @var \Zend_Filter_Interface $filterMock */
+        /** This filter should be applied to 'field1' field value only */
+        $filterMock = $this->getMock('Zend_Filter_Interface', [], [], '', false);
+        $filterMock->expects($this->exactly(1))->method('filter')->will(
+            $this->returnCallback(
+                function ($input) {
+                    return '(' . $input . ')';
+                }
+            )
+        );
+        $inputFilter->addFilter('field1', $filterMock);
+
+        /** Execute SUT and ensure that array items were filtered correctly */
+        $inputArray = ['field1' => 'value1', 'field2' => 'value2'];
+        $expectedOutput = ['field1' => '(value1)', 'field2' => 'value2'];
+        $this->assertEquals($expectedOutput, $inputFilter->filter($inputArray), 'Array was filtered incorrectly.');
+    }
+
+    public function testFilterZendFilterAsArray()
+    {
+        $objectManagerMock = $this->getMock('Magento\Framework\ObjectManager', [], [], '', false);
+        $inputFilter = new Input($objectManagerMock);
+
+        /** This filter should be applied to 'field1' field value only */
+        $inputFilter->setFilters(
+            array(
+                'field1' => array(
+                    array(
+                        'zend' => 'StringToUpper',
+                        'args' => array('encoding' => 'utf-8')
+                    )
+                )
+            )
+        );
+
+        /** Execute SUT and ensure that array items were filtered correctly */
+        $inputArray = ['field1' => 'value1', 'field2' => 'value2'];
+        $expectedOutput = ['field1' => 'VALUE1', 'field2' => 'value2'];
+        $this->assertEquals($expectedOutput, $inputFilter->filter($inputArray), 'Array was filtered incorrectly.');
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/Object/GridTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/Object/GridTest.php
new file mode 100644
index 00000000000..d6fb3367a56
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/Object/GridTest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter\Object;
+
+use Magento\Framework\Object;
+
+class GridTest extends \PHPUnit_Framework_TestCase
+{
+    public function testFilter()
+    {
+        $entityFactoryMock = $this->getMock(
+            'Magento\Framework\Data\Collection\EntityFactoryInterface',
+            [],
+            [],
+            '',
+            false
+        );
+        $entityFactoryMock
+            ->expects($this->any())
+            ->method('create')
+            ->with('Magento\Framework\Object', [])
+            ->will(
+                $this->returnCallback(
+                    function () {
+                        return new Object();
+                    }
+                )
+            );
+
+        $gridFilter = new Grid($entityFactoryMock);
+        $grid = [
+            new Object(['field1' => 'value11', 'field2' => 'value12']),
+            new Object(['field3' => 'value23', 'field2' => 'value22']),
+        ];
+
+        /** @var \Zend_Filter_Interface $filterMock */
+        /** This filter should be applied to all fields values */
+        $filterMock = $this->getMock('Zend_Filter_Interface', [], [], '', false);
+        $filterMock->expects($this->exactly(4))->method('filter')->will(
+            $this->returnCallback(
+                function ($input) {
+                    return '(' . $input . ')';
+                }
+            )
+        );
+        $gridFilter->addFilter($filterMock);
+
+        /** @var \Zend_Filter_Interface $fieldFilterMock */
+        /** This filter should be applied to 'field2' field value only */
+        $fieldFilterMock = $this->getMock('Zend_Filter_Interface', [], [], '', false);
+        $fieldFilterMock->expects($this->exactly(2))->method('filter')->will(
+            $this->returnCallback(
+                function ($input) {
+                    return '[' . $input . ']';
+                }
+            )
+        );
+        $gridFilter->addFilter($fieldFilterMock, 'field2');
+
+        /** Execute SUT and ensure that data of grid items was filtered correctly */
+        $filteredGrid = $gridFilter->filter($grid);
+        $this->assertCount(2, $filteredGrid, 'Quantity of filtered items is invalid.');
+        $this->assertEquals(
+            ['field1' => '(value11)', 'field2' => '[(value12)]'],
+            $filteredGrid[0]->getData(),
+            'First grid item was filtered incorrectly.'
+        );
+        $this->assertEquals(
+            ['field3' => '(value23)', 'field2' => '[(value22)]'],
+            $filteredGrid[1]->getData(),
+            'Second grid item was filtered incorrectly.'
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/SprintfTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/SprintfTest.php
new file mode 100644
index 00000000000..0a4e40a2500
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/SprintfTest.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter;
+
+class SprintfTest extends \PHPUnit_Framework_TestCase
+{
+    public function testFilter()
+    {
+        $sprintfFilter = new \Magento\Framework\Filter\Sprintf('Formatted value: "%s"', 2, ',', ' ');
+        $this->assertEquals('Formatted value: "1 234,57"', $sprintfFilter->filter(1234.56789));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/ParameterTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/ParameterTest.php
new file mode 100644
index 00000000000..7fbeaa0c98e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/ParameterTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Filter\Template\Tokenizer;
+
+class ParameterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Filter\Template\Tokenizer\Parameter
+     */
+    protected $_filter;
+
+    protected function setUp()
+    {
+        $this->_filter = new Parameter();
+    }
+
+    /**
+     * @param string $string String to tokenize
+     * @param string $expectedValue
+     * @dataProvider sampleTokenizeStringProvider
+     */
+    public function testTokenize($string, $expectedValue)
+    {
+        $this->_filter->setString($string);
+        $this->assertEquals($expectedValue, $this->_filter->tokenize());
+    }
+
+    /**
+     * @param string $string String to get value of
+     * @param string $expectedValue
+     * @dataProvider sampleGetValueStringProvider
+     */
+    public function testGetValue($string, $expectedValue)
+    {
+        $this->_filter->setString($string);
+        $this->assertEquals($expectedValue, $this->_filter->getValue());
+    }
+
+    public function sampleTokenizeStringProvider()
+    {
+        return [
+            [" direct_url='about-magento-demo-store'", ['direct_url' => 'about-magento-demo-store']],
+            [" direct_url='about-magento-demo-store\\[newDemo]", ['direct_url' => 'about-magento-demo-store[newDemo]']],
+            ["   ", []]
+        ];
+    }
+
+    public function sampleGetValueStringProvider()
+    {
+        return [
+            [" direct_url='about-magento-demo-store'", "direct_url='about-magento-demo-store'"],
+            [" direct_url='about-magento-demo-store\\[newDemo]", "direct_url='about-magento-demo-store[newDemo]"],
+            ['   ', '']
+        ];
+    }
+}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Layout/FilesTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/VariableTest.php
similarity index 50%
rename from dev/tests/static/testsuite/Magento/Test/Integrity/Layout/FilesTest.php
rename to dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/VariableTest.php
index ba93af24112..8d80d4875ee 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Layout/FilesTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/Template/Tokenizer/VariableTest.php
@@ -21,35 +21,40 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Test\Integrity\Layout;
+namespace Magento\Framework\Filter\Template\Tokenizer;
 
-class FilesTest extends \PHPUnit_Framework_TestCase
+class VariableTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var string
+     * @var \Magento\Framework\Filter\Template\Tokenizer\Variable
      */
-    protected $_schemaFile;
+    protected $_filter;
 
     protected function setUp()
     {
-        $this->_schemaFile = \Magento\TestFramework\Utility\Files::init()->getModuleFile(
-            'Magento',
-            'Core',
-            'etc/layout_single.xsd'
-        );
+        $this->_filter = new Variable();
     }
 
-    public function testLayouts()
+    /**
+     * @param string $string String to tokenize
+     * @param string $expectedValue
+     * @dataProvider sampleTokenizeStringProvider
+     */
+    public function testTokenize($string, $expectedValue)
+    {
+        $this->_filter->setString($string);
+        $this->assertEquals($expectedValue, $this->_filter->tokenize());
+    }
+
+    public function sampleTokenizeStringProvider()
     {
-        $invoker = new \Magento\TestFramework\Utility\AggregateInvoker($this);
-        $invoker(
-            function ($layout) {
-                $dom = new \DOMDocument();
-                $dom->loadXML(file_get_contents($layout));
-                $errors = \Magento\TestFramework\Utility\Validator::validateXml($dom, $this->_schemaFile);
-                $this->assertTrue(empty($errors), print_r($errors, true));
-            },
-            \Magento\TestFramework\Utility\Files::init()->getLayoutFiles()
-        );
+        return [
+            ["firstname", [['type' => 'variable', 'name' => 'firstname']]],
+            [
+                "invoke(arg1, arg2, 2, 2.7, -1, 'Mike\\'s')",
+                [['type' => 'method', 'name' => 'invoke', 'args' => ['arg1', 'arg2', 2, 2.7, -1, "Mike's"]]]
+            ],
+            ["  ", []]
+        ];
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Filter/TemplateTest.php b/dev/tests/unit/testsuite/Magento/Framework/Filter/TemplateTest.php
new file mode 100644
index 00000000000..b3cc3cb4d08
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Filter/TemplateTest.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Filter;
+
+class TemplateTest extends \PHPUnit_Framework_TestCase
+{
+    public function testFilter()
+    {
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        /** @var \Magento\Framework\Filter\Template $templateFilter */
+        $templateFilter = $objectManager->getObject('Magento\Framework\Filter\Template');
+        $templateFilter->setVariables(
+            [
+                'customer' => new \Magento\Framework\Object(['firstname' => 'Felicia', 'lastname' => 'Henry']),
+                'company' => 'A. L. Price',
+                'street1' => '687 Vernon Street',
+                'city' => 'Parker Dam',
+                'region' => 'CA',
+                'postcode' => '92267',
+                'telephone' => '760-663-5876',
+            ]
+        );
+
+        $template = <<<TEMPLATE
+{{var customer.firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var customer.getLastname()}}
+{{depend company}}{{var company}}{{/depend}}
+{{if street1}}{{var street1}}
+{{/if}}
+{{depend street2}}{{var street2}}{{/depend}}
+{{depend street3}}{{var street3}}{{/depend}}
+{{depend street4}}{{var street4}}{{/depend}}
+{{if city}}{{var city}},  {{/if}}{{if region}}{{var region}}, {{/if}}{{if postcode}}{{var postcode}}{{/if}}
+{{var country}}
+T: {{var telephone}}
+{{depend fax}}F: {{var fax}}{{/depend}}
+{{depend vat_id}}VAT: {{var vat_id}}{{/depend}}
+TEMPLATE;
+
+        $expectedResult = <<<EXPECTED_RESULT
+Felicia Henry
+A. L. Price
+687 Vernon Street
+
+
+
+
+Parker Dam,  CA, 92267
+
+T: 760-663-5876
+
+
+EXPECTED_RESULT;
+
+        $this->assertEquals($expectedResult, $templateFilter->filter($template), 'Template was processed incorrectly');
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/AggregatedTest.php b/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/AggregatedTest.php
new file mode 100644
index 00000000000..48415e933f8
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/AggregatedTest.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Less\File\Collector;
+
+/**
+ * Tests Aggregate
+ */
+class AggregatedTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @var \Magento\Framework\View\File\FileList\Factory|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileListFactoryMock;
+
+    /**
+     * @var \Magento\Framework\View\File\FileList|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileListMock;
+
+    /**
+     * @var \Magento\Framework\View\File\CollectorInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $libraryFilesMock;
+
+    /**
+     * @var \Magento\Framework\View\File\CollectorInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $baseFilesMock;
+
+    /**
+     * @var \Magento\Framework\View\File\CollectorInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $overriddenBaseFilesMock;
+
+    /**
+     * @var \Magento\Framework\View\Design\ThemeInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $themeMock;
+
+    /**
+     * Setup tests
+     * @return void
+     */
+    public function setup()
+    {
+        $this->fileListFactoryMock = $this->getMockBuilder('Magento\Framework\View\File\FileList\Factory')
+            ->disableOriginalConstructor()->getMock();
+        $this->fileListMock = $this->getMockBuilder('Magento\Framework\View\File\FileList')
+            ->disableOriginalConstructor()->getMock();
+        $this->fileListFactoryMock->expects($this->any())->method('create')
+            ->will($this->returnValue($this->fileListMock));
+        $this->libraryFilesMock = $this->getMockBuilder('Magento\Framework\View\File\CollectorInterface')
+            ->getMock();
+
+        $this->baseFilesMock = $this->getMockBuilder('Magento\Framework\View\File\CollectorInterface')->getMock();
+        $this->overriddenBaseFilesMock = $this->getMockBuilder('Magento\Framework\View\File\CollectorInterface')
+            ->getMock();
+        $this->themeMock = $this->getMockBuilder('\Magento\Framework\View\Design\ThemeInterface')->getMock();
+    }
+
+    /**
+     * Tests exception path of no files
+     *
+     * @expectedException \LogicException
+     * @expectedExceptionMessage magento_import returns empty result by path
+     *
+     * @return void
+     */
+    public function testGetFilesEmpty()
+    {
+        $this->libraryFilesMock->expects($this->any())->method('getFiles')->will($this->returnValue([]));
+        $this->baseFilesMock->expects($this->any())->method('getFiles')->will($this->returnValue([]));
+        $this->overriddenBaseFilesMock->expects($this->any())->method('getFiles')->will($this->returnValue([]));
+
+        $aggregated = new Aggregated(
+            $this->fileListFactoryMock,
+            $this->libraryFilesMock,
+            $this->baseFilesMock,
+            $this->overriddenBaseFilesMock
+        );
+
+        $this->themeMock->expects($this->any())->method('getInheritedThemes')->will($this->returnValue([]));
+
+        $aggregated->getFiles($this->themeMock, '*');
+    }
+
+    /**
+     *
+     * @dataProvider getFilesDataProvider
+     *
+     * @param $libraryFiles array Files in lib directory
+     * @param $baseFiles array Files in base directory
+     * @param $themeFiles array Files in theme
+     * *
+     * @return void
+     */
+    public function testGetFiles($libraryFiles, $baseFiles, $themeFiles)
+    {
+        $this->fileListMock->expects($this->at(0))->method('add')->with($this->equalTo($libraryFiles));
+        $this->fileListMock->expects($this->at(1))->method('add')->with($this->equalTo($baseFiles));
+        $this->fileListMock->expects($this->any())->method('getAll')->will($this->returnValue(['returnedFile']));
+
+        $subPath = '*';
+        $this->libraryFilesMock->expects($this->atLeastOnce())
+            ->method('getFiles')
+            ->with($this->themeMock, $subPath)
+            ->will($this->returnValue($libraryFiles));
+
+        $this->baseFilesMock->expects($this->atLeastOnce())
+            ->method('getFiles')
+            ->with($this->themeMock, $subPath)
+            ->will($this->returnValue($baseFiles));
+
+        $this->overriddenBaseFilesMock->expects($this->any())
+            ->method('getFiles')
+            ->will($this->returnValue($themeFiles));
+
+        $aggregated = new Aggregated(
+            $this->fileListFactoryMock,
+            $this->libraryFilesMock,
+            $this->baseFilesMock,
+            $this->overriddenBaseFilesMock
+        );
+
+        $inheritedThemeMock = $this->getMockBuilder('\Magento\Framework\View\Design\ThemeInterface')->getMock();
+        $this->themeMock->expects($this->any())->method('getInheritedThemes')
+            ->will($this->returnValue([$inheritedThemeMock]));
+
+        $this->assertEquals(['returnedFile'], $aggregated->getFiles($this->themeMock, $subPath));
+    }
+
+    /**
+     * Provides test data for testGetFiles()
+     *
+     * @return array
+     */
+    public function getFilesDataProvider()
+    {
+        return [
+            'all files' => [['file1'], ['file2'], ['file3']],
+            'no library' => [[], ['file1', 'file2'], ['file3']],
+        ];
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/LibraryTest.php b/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/LibraryTest.php
new file mode 100644
index 00000000000..0caee1dab7e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Less/File/Collector/LibraryTest.php
@@ -0,0 +1,175 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Framework\Less\File\Collector;
+
+use Magento\Framework\App\Filesystem;
+
+/**
+ * Tests Library
+ */
+class LibraryTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @var \Magento\Framework\View\File\FileList\Factory|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileListFactoryMock;
+
+    /**
+     * @var \Magento\Framework\App\Filesystem|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileSystemMock;
+
+    /**
+     * @var \Magento\Framework\View\File\Factory|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileFactoryMock;
+
+    /**
+     * @var \Magento\Framework\View\File\FileList|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $fileListMock;
+
+    /**
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $libraryDirectoryMock;
+
+    /**
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $themesDirectoryMock;
+
+    /**
+     * @var \Magento\Framework\View\Design\ThemeInterface|PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $themeMock;
+
+    /**
+     * Setup tests
+     * @return void
+     */
+    public function setup()
+    {
+        $this->fileListFactoryMock = $this->getMockBuilder('Magento\Framework\View\File\FileList\Factory')
+            ->disableOriginalConstructor()->getMock();
+        $this->fileListMock = $this->getMockBuilder('Magento\Framework\View\File\FileList')
+            ->disableOriginalConstructor()->getMock();
+        $this->fileListFactoryMock->expects($this->any())->method('create')
+            ->will($this->returnValue($this->fileListMock));
+
+        $this->fileSystemMock = $this->getMockBuilder('Magento\Framework\App\Filesystem')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->libraryDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
+            ->getMock();
+        $this->themesDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
+            ->getMock();
+        $this->fileSystemMock->expects($this->any())->method('getDirectoryRead')
+            ->will(
+                $this->returnValueMap(
+                    [
+                        [Filesystem::LIB_WEB, $this->libraryDirectoryMock],
+                        [Filesystem::THEMES_DIR, $this->themesDirectoryMock],
+                    ]
+                )
+            );
+
+        $this->fileFactoryMock = $this->getMockBuilder('Magento\Framework\View\File\Factory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->themeMock = $this->getMockBuilder('\Magento\Framework\View\Design\ThemeInterface')->getMock();
+    }
+
+    public function testGetFilesEmpty()
+    {
+        $this->libraryDirectoryMock->expects($this->any())->method('search')->will($this->returnValue([]));
+        $this->themeMock->expects($this->any())->method('getInheritedThemes')->will($this->returnValue([]));
+
+        // Verify search/replace are never called if no inheritedThemes
+        $this->themesDirectoryMock->expects($this->never())->method('search');
+        $this->fileListMock->expects($this->never())->method('replace');
+
+        $library = new Library(
+            $this->fileListFactoryMock,
+            $this->fileSystemMock,
+            $this->fileFactoryMock
+        );
+        $library->getFiles($this->themeMock, '*');
+    }
+
+    /**
+     *
+     * @dataProvider getFilesDataProvider
+     *
+     * @param $libraryFiles array Files in lib directory
+     * @param $themeFiles array Files in theme
+     * *
+     * @return void
+     */
+    public function testGetFiles($libraryFiles, $themeFiles)
+    {
+        $this->fileListMock->expects($this->any())->method('getAll')->will($this->returnValue(['returnedFile']));
+
+        $this->libraryDirectoryMock->expects($this->any())->method('search')->will($this->returnValue($libraryFiles));
+        $this->libraryDirectoryMock->expects($this->any())->method('getAbsolutePath')->will($this->returnCallback(
+            function ($file) {
+                    return '/opt/Magneto/lib/' . $file;
+            }
+        ));
+        $themePath = '/var/Magento/ATheme';
+        $subPath = '*';
+
+        $this->themesDirectoryMock->expects($this->any())
+            ->method('search')
+            ->with($themePath . '/web/' . $subPath)
+            ->will($this->returnValue($themeFiles));
+
+        $library = new Library(
+            $this->fileListFactoryMock,
+            $this->fileSystemMock,
+            $this->fileFactoryMock
+        );
+
+        $inheritedThemeMock = $this->getMockBuilder('\Magento\Framework\View\Design\ThemeInterface')->getMock();
+        $inheritedThemeMock->expects($this->any())->method('getFullPath')->will($this->returnValue($themePath));
+        $this->themeMock->expects($this->any())->method('getInheritedThemes')
+            ->will($this->returnValue([$inheritedThemeMock]));
+
+        $this->assertEquals(['returnedFile'], $library->getFiles($this->themeMock, $subPath));
+    }
+
+    /**
+     * Provides test data for testGetFiles()
+     *
+     * @return array
+     */
+    public function getFilesDataProvider()
+    {
+        return [
+            'all files' => [['file1'], ['file2']],
+            'no library' => [[], ['file1', 'file2']],
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/Locale/ConfigTest.php
new file mode 100644
index 00000000000..49fd8877c89
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Locale/ConfigTest.php
@@ -0,0 +1,224 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Locale;
+
+class ConfigTest extends \PHPUnit_Framework_TestCase
+{
+    private static $allAllowedLocales = [
+        'af_ZA', 'ar_DZ', 'ar_EG', 'ar_KW', 'ar_MA', 'ar_SA', 'az_AZ', 'be_BY', 'bg_BG', 'bn_BD',
+        'bs_BA', 'ca_ES', 'cs_CZ', 'cy_GB', 'da_DK', 'de_AT', 'de_CH', 'de_DE', 'el_GR', 'en_AU',
+        'en_CA', 'en_GB', 'en_NZ', 'en_US', 'es_AR', 'es_CO', 'es_PA', 'gl_ES', 'es_CR', 'es_ES',
+        'es_MX', 'es_EU', 'es_PE', 'et_EE', 'fa_IR', 'fi_FI', 'fil_PH', 'fr_CA', 'fr_FR', 'gu_IN',
+        'he_IL', 'hi_IN', 'hr_HR', 'hu_HU', 'id_ID', 'is_IS', 'it_CH', 'it_IT', 'ja_JP', 'ka_GE',
+        'km_KH', 'ko_KR', 'lo_LA', 'lt_LT', 'lv_LV', 'mk_MK', 'mn_MN', 'ms_MY', 'nl_NL', 'nb_NO',
+        'nn_NO', 'pl_PL', 'pt_BR', 'pt_PT', 'ro_RO', 'ru_RU', 'sk_SK', 'sl_SI', 'sq_AL', 'sr_RS',
+        'sv_SE', 'sw_KE', 'th_TH', 'tr_TR', 'uk_UA', 'vi_VN', 'zh_CN', 'zh_HK', 'zh_TW', 'es_CL',
+        'lo_LA', 'es_VE', 'en_IE',
+    ];
+
+    private static $allAllowedCurrencies = [
+        'AFN', 'ALL', 'AZN', 'DZD', 'AOA', 'ARS', 'AMD', 'AWG', 'AUD', 'BSD',
+        'BHD', 'BDT', 'BBD', 'BYR', 'BZD', 'BMD', 'BTN', 'BOB', 'BAM', 'BWP',
+        'BRL', 'GBP', 'BND', 'BGN', 'BUK', 'BIF', 'KHR', 'CAD', 'CVE', 'CZK',
+        'KYD', 'GQE', 'CLP', 'CNY', 'COP', 'KMF', 'CDF', 'CRC', 'HRK', 'CUP',
+        'DKK', 'DJF', 'DOP', 'XCD', 'EGP', 'SVC', 'ERN', 'EEK', 'ETB', 'EUR',
+        'FKP', 'FJD', 'GMD', 'GEK', 'GEL', 'GHS', 'GIP', 'GTQ', 'GNF', 'GYD',
+        'HTG', 'HNL', 'HKD', 'HUF', 'ISK', 'INR', 'IDR', 'IRR', 'IQD', 'ILS',
+        'JMD', 'JPY', 'JOD', 'KZT', 'KES', 'KWD', 'KGS', 'LAK', 'LVL', 'LBP',
+        'LSL', 'LRD', 'LYD', 'LTL', 'MOP', 'MKD', 'MGA', 'MWK', 'MYR', 'MVR',
+        'LSM', 'MRO', 'MUR', 'MXN', 'MDL', 'MNT', 'MAD', 'MZN', 'MMK', 'NAD',
+        'NPR', 'ANG', 'YTL', 'NZD', 'NIC', 'NGN', 'KPW', 'NOK', 'OMR', 'PKR',
+        'PAB', 'PGK', 'PYG', 'PEN', 'PHP', 'PLN', 'QAR', 'RHD', 'RON', 'RUB',
+        'RWF', 'SHP', 'STD', 'SAR', 'RSD', 'SCR', 'SLL', 'SGD', 'SKK', 'SBD',
+        'SOS', 'ZAR', 'KRW', 'LKR', 'SDG', 'SRD', 'SZL', 'SEK', 'CHF', 'SYP',
+        'TWD', 'TJS', 'TZS', 'THB', 'TOP', 'TTD', 'TND', 'TMM', 'USD', 'UGX',
+        'UAH', 'AED', 'UYU', 'UZS', 'VUV', 'VEB', 'VEF', 'VND', 'CHE', 'CHW',
+        'XOF', 'WST', 'YER', 'ZMK', 'ZWD', 'TRY', 'AZM', 'ROL', 'TRL', 'XPF',
+    ];
+
+    private static $samplePresentLocales = [
+         'en_US', 'lv_LV', 'pt_BR', 'it_IT', 'ar_EG', 'bg_BG', 'en_IE', 'es_ES',
+         'en_AU', 'pt_PT', 'ru_RU', 'en_CA', 'vi_VN', 'ja_JP', 'en_GB', 'zh_CN',
+         'zh_TW', 'fr_FR', 'ar_KW', 'pl_PL', 'ko_KR', 'sk_SK', 'el_GR', 'hi_IN',
+    ];
+
+    private static $sampleAbsentLocales = [
+        'aa_BB', 'foo_BAR', 'cc_DD',
+    ];
+
+    private static $sampleAdditionalLocales = [
+        'en_AA', 'es_ZZ',
+    ];
+
+    private static $samplePresentCurrencies = [
+        'AUD', 'BBD', 'GBP', 'CAD', 'CZK', 'GQE', 'CNY', 'DJF', 'HKD', 'JPY', 'MYR',
+        'MXN', 'NZD', 'PHP', 'SGD', 'CHF', 'TWD', 'USD', 'AED', 'ZWD', 'ROL', 'CHE',
+    ];
+
+    private static $sampleAbsentCurrencies = [
+        'ABC', 'DEF', 'GHI', 'ZZZ',
+    ];
+
+    private static $sampleAdditionalCurrencies = [
+        'QED', 'PNP', 'EJN', 'MTO', 'EBY',
+    ];
+
+    /** @var  \Magento\Framework\Locale\Config */
+    private $configObject;
+
+
+    public function testGetAllowedLocalesNoDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config');
+
+        $retrievedLocales = $this->configObject->getAllowedLocales();
+
+        $differences = array_diff($this::$allAllowedLocales, $retrievedLocales);
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentLocales as $absentLocale) {
+            $this->assertNotContains($absentLocale, $retrievedLocales);
+        }
+    }
+
+    public function testGetAllowedLocalesGivenDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config',
+                [
+                    'data' => [
+                        'allowedLocales' => $this::$sampleAdditionalLocales,
+                    ],
+                ]
+            );
+
+        $retrievedLocalesWithAdditions = $this->configObject->getAllowedLocales();
+
+        $differences = array_diff(
+            array_unique(array_merge($this::$allAllowedLocales, $this::$sampleAdditionalLocales)),
+            $retrievedLocalesWithAdditions
+        );
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentLocales as $absentLocale) {
+            $this->assertNotContains($absentLocale, $retrievedLocalesWithAdditions);
+        }
+    }
+
+    public function testGetAllowedLocalesGivenRedundantDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config',
+                [
+                    'data' => [
+                        'allowedLocales' => $this::$samplePresentLocales,
+                    ],
+                ]
+            );
+
+        $retrievedLocalesWithRedundencies = $this->configObject->getAllowedLocales();
+
+        $differences = array_diff(
+            $this::$allAllowedLocales,
+            $retrievedLocalesWithRedundencies
+        );
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentLocales as $absentLocale) {
+            $this->assertNotContains($absentLocale, $retrievedLocalesWithRedundencies);
+        }
+    }
+
+    public function testGetAllowedCurrenciesNoDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config');
+
+        $retrievedCurrencies = $this->configObject->getAllowedCurrencies();
+
+        $differences = array_diff($this::$allAllowedCurrencies, $retrievedCurrencies);
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentCurrencies as $absentCurrency) {
+            $this->assertNotContains($absentCurrency, $retrievedCurrencies);
+        }
+    }
+
+    public function testGetAllowedCurrenciesGivenDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config',
+                [
+                    'data' => [
+                        'allowedCurrencies' => $this::$sampleAdditionalCurrencies,
+                    ],
+                ]
+            );
+
+        $retrievedCurrenciesWithAdditions = $this->configObject->getAllowedCurrencies();
+
+        $differences = array_diff(
+            array_unique(array_merge($this::$allAllowedCurrencies, $this::$samplePresentCurrencies)),
+            $retrievedCurrenciesWithAdditions
+        );
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentCurrencies as $absentCurrency) {
+            $this->assertNotContains($absentCurrency, $retrievedCurrenciesWithAdditions);
+        }
+    }
+
+
+    public function testGetAllowedCurrenciesGivenRedundantDataArray()
+    {
+        $this->configObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Config',
+                [
+                    'data' => [
+                        'allowedCurrencies' => $this::$samplePresentCurrencies,
+                    ],
+                ]
+            );
+
+        $retrievedCurrenciesWithRedundencies = $this->configObject->getAllowedCurrencies();
+
+        $differences = array_diff(
+            $this::$allAllowedCurrencies,
+            $retrievedCurrenciesWithRedundencies
+        );
+
+        $this->assertEmpty($differences);
+
+        foreach ($this::$sampleAbsentCurrencies as $absentCurrency) {
+            $this->assertNotContains($absentCurrency, $retrievedCurrenciesWithRedundencies);
+        }
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/CurrencyTest.php b/dev/tests/unit/testsuite/Magento/Framework/Locale/CurrencyTest.php
new file mode 100644
index 00000000000..85d5b410d8f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Locale/CurrencyTest.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Locale;
+use Magento\Framework\Locale\CurrencyInterface;
+
+
+class CurrencyTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Event\Manager | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $mockEventManager;
+
+    /**
+     * @var \Magento\Framework\Locale\Resolver | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $mockLocaleResolver;
+
+    /**
+     * @var \Magento\Framework\CurrencyFactory | \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $mockCurrencyFactory;
+
+    /**
+     * @var \Magento\Framework\Locale\Currency
+     */
+    private $testCurrencyObject;
+
+    const TEST_NONCACHED_CURRENCY = 'USD';
+    const TEST_NONCACHED_CURRENCY_LOCALE = 'en_US';
+    const TEST_CACHED_CURRENCY = 'CAD';
+    const TEST_CACHED_CURRENCY_LOCALE = 'en_CA';
+    const TEST_NONEXISTANT_CURRENCY = 'QQQ';
+    const TEST_NONEXISTANT_CURRENCY_LOCALE = 'fr_FR';
+    const TEST_EXCEPTION_CURRENCY = 'ZZZ';
+    const TEST_EXCEPTION_CURRENCY_LOCALE = 'es_ES';
+
+    public function setUp()
+    {
+        $this->mockEventManager = $this
+            ->getMockBuilder('\Magento\Framework\Event\Manager')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockLocaleResolver = $this
+            ->getMockBuilder('\Magento\Framework\Locale\Resolver')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->mockCurrencyFactory = $this
+            ->getMockBuilder('\Magento\Framework\CurrencyFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->testCurrencyObject = (new \Magento\TestFramework\Helper\ObjectManager($this))
+            ->getObject('Magento\Framework\Locale\Currency',
+                [
+                    'eventManager'     => $this->mockEventManager,
+                    'localeResolver'   => $this->mockLocaleResolver,
+                    'currencyFactory'  => $this->mockCurrencyFactory,
+                ]
+            );
+    }
+
+    public function testGetDefaultCurrency()
+    {
+        $expectedDefaultCurrency = CurrencyInterface::DEFAULT_CURRENCY;
+        $retrievedDefaultCurrency = $this->testCurrencyObject->getDefaultCurrency();
+        $this->assertEquals($expectedDefaultCurrency, $retrievedDefaultCurrency);
+    }
+
+    public function testGetCurrencyNonCached()
+    {
+        $options = new \Zend_Currency(null, self::TEST_NONCACHED_CURRENCY_LOCALE);
+
+        $this->mockCurrencyFactory
+            ->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($options));
+
+        $this->mockEventManager
+            ->expects($this->once())
+            ->method('dispatch');
+
+        $retrievedCurrencyObject = $this->testCurrencyObject
+            ->getCurrency(self::TEST_NONCACHED_CURRENCY);
+
+        $this->assertInstanceOf('Zend_Currency', $retrievedCurrencyObject);
+        $this->assertEquals(self::TEST_NONCACHED_CURRENCY_LOCALE, $retrievedCurrencyObject->getLocale());
+        $this->assertEquals('US Dollar', $retrievedCurrencyObject->getName());
+        $this->assertEquals([self::TEST_NONCACHED_CURRENCY], $retrievedCurrencyObject->getCurrencyList());
+    }
+
+    public function testGetCurrencyCached()
+    {
+        $options = new \Zend_Currency(null, self::TEST_CACHED_CURRENCY_LOCALE);
+
+        $this->mockCurrencyFactory
+            ->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($options));
+
+        $this->mockEventManager
+            ->expects($this->once())
+            ->method('dispatch');
+
+        $retrievedCurrencyObject = $this->testCurrencyObject
+            ->getCurrency(self::TEST_CACHED_CURRENCY);
+
+        $this->assertInstanceOf('Zend_Currency', $retrievedCurrencyObject);
+        $this->assertEquals(self::TEST_CACHED_CURRENCY_LOCALE, $retrievedCurrencyObject->getLocale());
+        $this->assertEquals('Canadian Dollar', $retrievedCurrencyObject->getName());
+        $this->assertEquals([self::TEST_CACHED_CURRENCY], $retrievedCurrencyObject->getCurrencyList());
+
+        /*
+         * Since the CAD currency object was previously retrieved, getCurrency()
+         * should return the previously created and cached currency object for CAD, rather
+         * than creating another one.
+         */
+
+        $this->mockCurrencyFactory
+            ->expects($this->never())
+            ->method('create')
+            ->will($this->returnValue($options));
+
+        $this->mockEventManager
+            ->expects($this->never())
+            ->method('dispatch');
+
+        $retrievedCurrencyObject = $this->testCurrencyObject
+            ->getCurrency(self::TEST_CACHED_CURRENCY);
+
+        $this->assertInstanceOf('Zend_Currency', $retrievedCurrencyObject);
+        $this->assertEquals(self::TEST_CACHED_CURRENCY_LOCALE, $retrievedCurrencyObject->getLocale());
+        $this->assertEquals('Canadian Dollar', $retrievedCurrencyObject->getName());
+        $this->assertEquals([self::TEST_CACHED_CURRENCY], $retrievedCurrencyObject->getCurrencyList());
+    }
+
+    public function testGetNonExistantCurrency()
+    {
+        $options = new \Zend_Currency(null, self::TEST_NONEXISTANT_CURRENCY_LOCALE);
+
+        $this->mockCurrencyFactory
+            ->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($options));
+
+        $this->mockEventManager
+            ->expects($this->once())
+            ->method('dispatch');
+
+        $this->mockEventManager
+            ->expects($this->once())
+            ->method('dispatch');
+
+        $retrievedCurrencyObject = $this->testCurrencyObject
+            ->getCurrency(self::TEST_NONEXISTANT_CURRENCY);
+
+        $this->assertInstanceOf('Zend_Currency', $retrievedCurrencyObject);
+        $this->assertEquals(self::TEST_NONEXISTANT_CURRENCY_LOCALE, $retrievedCurrencyObject->getLocale());
+        $this->assertEquals('euro', $retrievedCurrencyObject->getName());
+        $this->assertEquals(['EUR'], $retrievedCurrencyObject->getCurrencyList());
+    }
+
+    public function testExceptionCase()
+    {
+        $options = new \Zend_Currency(null, self::TEST_EXCEPTION_CURRENCY_LOCALE);
+
+        $this->mockCurrencyFactory
+            ->expects($this->at(0))
+            ->method('create')
+            ->will($this->throwException(new \Exception));
+
+        $this->mockCurrencyFactory
+            ->expects($this->at(1))
+            ->method('create')
+            ->will($this->returnValue($options));
+
+        $this->mockEventManager
+            ->expects($this->once())
+            ->method('dispatch');
+
+        $this->mockLocaleResolver
+            ->expects($this->exactly(2))
+            ->method('getLocale');
+
+        $retrievedCurrencyObject = $this->testCurrencyObject
+            ->getCurrency(self::TEST_EXCEPTION_CURRENCY);
+
+        $this->assertInstanceOf('Zend_Currency', $retrievedCurrencyObject);
+        $this->assertEquals(self::TEST_EXCEPTION_CURRENCY_LOCALE, $retrievedCurrencyObject->getLocale());
+        $this->assertEquals(self::TEST_EXCEPTION_CURRENCY, $retrievedCurrencyObject->getName());
+        $this->assertEquals(['EUR'], $retrievedCurrencyObject->getCurrencyList());
+    }
+}
\ No newline at end of file
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/ConverterTest.php
deleted file mode 100644
index d9383c0403b..00000000000
--- a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/ConverterTest.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy\Config;
-
-class ConverterTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Framework\Locale\Hierarchy\Config\Converter
-     */
-    protected $_model;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $_configMock;
-
-    protected function setUp()
-    {
-        $this->_model = new \Magento\Framework\Locale\Hierarchy\Config\Converter();
-    }
-
-    /**
-     * @dataProvider composeLocaleHierarchyDataProvider
-     */
-    public function testComposeLocaleHierarchy($localeConfig, $localeHierarchy)
-    {
-        $dom = new \DOMDocument();
-        $dom->loadXML($localeConfig);
-        $this->assertEquals($localeHierarchy, $this->_model->convert($dom));
-    }
-
-    public function composeLocaleHierarchyDataProvider()
-    {
-        return array(
-            array(
-                'xml' => '<config><locale code="en_US" parent="en_UK" /><locale code="en_UK" parent="pt_BR"/></config>',
-                array('en_US' => array('pt_BR', 'en_UK'), 'en_UK' => array('pt_BR'))
-            ),
-            array(
-                'xml' => '<config><locale code="en_US" parent="en_UK"/><locale code="en_UK" parent="en_US"/></config>',
-                array('en_US' => array('en_UK'), 'en_UK' => array('en_US'))
-            ),
-            array('xml' => '<config></config>', array())
-        );
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/FileResolverTest.php b/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/FileResolverTest.php
deleted file mode 100644
index 9ce88eaa746..00000000000
--- a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/Config/FileResolverTest.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy\Config;
-
-class FileResolverTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Framework\Locale\Hierarchy\Config\FileResolver
-     */
-    protected $_model;
-
-    /**
-     * @var \Magento\Framework\Filesystem\Directory\Read
-     */
-    protected $_directoryMock;
-
-    /**
-     * @var \Magento\Framework\Config\FileIteratorFactory
-     */
-    protected $iteratorFactory;
-
-    protected function setUp()
-    {
-        $filesystem = $this->getMock('Magento\Framework\App\Filesystem', array('getDirectoryRead'), array(), '', false);
-        $this->_directoryMock = $this->getMock(
-            '\Magento\Framework\Filesystem\Directory\Read',
-            array('isExist', 'search'),
-            array(),
-            '',
-            false
-        );
-        $filesystem->expects(
-            $this->once()
-        )->method(
-            'getDirectoryRead'
-        )->with(
-            \Magento\Framework\App\Filesystem::APP_DIR
-        )->will(
-            $this->returnValue($this->_directoryMock)
-        );
-        $this->_directoryMock->expects(
-            $this->once()
-        )->method(
-            'isExist'
-        )->with(
-            'locale'
-        )->will(
-            $this->returnValue(true)
-        );
-        $this->iteratorFactory = $this->getMock(
-            'Magento\Framework\Config\FileIteratorFactory',
-            array(),
-            array(),
-            '',
-            false
-        );
-        $this->_model = new \Magento\Framework\Locale\Hierarchy\Config\FileResolver(
-            $filesystem,
-            $this->iteratorFactory
-        );
-    }
-
-    /**
-     * @covers \Magento\Framework\Locale\Hierarchy\Config\FileResolver::get
-     */
-    public function testGet()
-    {
-        $paths = array(
-            __DIR__ . '/_files/custom/hierarchy_config.xml',
-            __DIR__ . '/_files/default/hierarchy_config.xml'
-        );
-        $expected = array(0 => $paths);
-
-        $this->_directoryMock->expects($this->once())->method('search')->will($this->returnValue(array($paths)));
-        $this->iteratorFactory->expects($this->once())->method('create')->will($this->returnValue(array($paths)));
-        $this->assertEquals($expected, $this->_model->get('hierarchy_config.xml', 'scope'));
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/ConfigTest.php
deleted file mode 100644
index a8f110ef276..00000000000
--- a/dev/tests/unit/testsuite/Magento/Framework/Locale/Hierarchy/ConfigTest.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy;
-
-class ConfigTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var \Magento\Framework\Locale\Hierarchy\Config
-     */
-    protected $_model;
-
-    /**
-     * @var \Magento\Framework\Locale\Hierarchy\Config\Reader
-     */
-    protected $_configReaderMock;
-
-    /**
-     * @var \Magento\Framework\Config\CacheInterface
-     */
-    protected $_cacheMock;
-
-    /**
-     * @var string
-     */
-    protected $_cacheId;
-
-    /**
-     * @var array
-     */
-    protected $_testData;
-
-    protected function setUp()
-    {
-        $this->_configReaderMock = $this->getMock(
-            '\Magento\Framework\Config\ReaderInterface',
-            array(),
-            array(),
-            '',
-            false
-        );
-        $this->_cacheMock = $this->getMock('Magento\Framework\Config\CacheInterface');
-        $this->_cacheId = 'customCacheId';
-
-        $this->_testData = array('key' => 'value');
-
-        $this->_cacheMock->expects(
-            $this->once()
-        )->method(
-            'load'
-        )->with(
-            $this->_cacheId
-        )->will(
-            $this->returnValue(serialize($this->_testData))
-        );
-
-        $this->_model = new \Magento\Framework\Locale\Hierarchy\Config(
-            $this->_configReaderMock,
-            $this->_cacheMock,
-            $this->_cacheId
-        );
-    }
-
-    public function testGetHierarchy()
-    {
-        $this->assertEquals($this->_testData, $this->_model->getHierarchy());
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/AbstractDbTest.php b/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/AbstractDbTest.php
new file mode 100644
index 00000000000..8b58d2c0743
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/AbstractDbTest.php
@@ -0,0 +1,389 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Model\Resource\Db;
+
+class AbstractDbTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Model\Resource\Db\AbstractDb
+     */
+    protected $_model;
+
+    /**
+     * @var \Magento\Framework\App\Resource
+     */
+    protected $_resourcesMock;
+
+    protected function setUp()
+    {
+        $this->_resourcesMock = $this->getMock(
+            '\Magento\Framework\App\Resource',
+            ['getConnection', 'getTableName', 'getTable'],
+            [],
+            '',
+            false
+        );
+
+        $this->_model = $this->getMockForAbstractClass(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            array($this->_resourcesMock)
+        );
+    }
+
+    /**
+     * @param $fieldNameType
+     * @param $expectedResult
+     * @dataProvider addUniqueFieldDataProvider
+     */
+    public function testAddUniqueField($fieldNameType, $expectedResult)
+    {
+        $this->_model->addUniqueField($fieldNameType);
+        $this->assertEquals($expectedResult, $this->_model->getUniqueFields());
+    }
+
+    /**
+     * @return array
+     */
+    public function addUniqueFieldDataProvider()
+    {
+        return [
+            [
+                'fieldNameString',
+                ['fieldNameString']
+            ],
+            [
+                [
+                    'fieldNameArray',
+                    'FieldNameArraySecond'
+                ],
+                [
+                    [
+                        'fieldNameArray',
+                        'FieldNameArraySecond'
+                    ]
+                ]
+            ],
+            [
+                null,
+                [null]
+            ]
+        ];
+    }
+
+    public function testAddUniqueFieldArray()
+    {
+        $this->assertInstanceOf(
+            '\Magento\Framework\Model\Resource\Db\AbstractDb',
+            $this->_model->addUniqueField(['someField'])
+        );
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     * @expectedExceptionMessage Empty identifier field name
+     */
+    public function testGetIdFieldNameException()
+    {
+        $this->_model->getIdFieldName();
+    }
+
+    public function testGetIdFieldname()
+    {
+        $data = 'MainTableName';
+        $idFieldNameProperty = new \ReflectionProperty(
+            'Magento\Framework\Model\Resource\Db\AbstractDb', '_idFieldName'
+        );
+        $idFieldNameProperty->setAccessible(true);
+        $idFieldNameProperty->setValue($this->_model, $data);
+        $this->assertEquals($data, $this->_model->getIdFieldName());
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     * @expectedExceptionMessage Empty main table name
+     */
+    public function testGetMainTableException()
+    {
+        $this->_model->getMainTable();
+    }
+
+    /**
+     * @dataProvider getTableDataProvider
+     * @param $tableName
+     * @param $expectedResult
+     */
+    public function testGetMainTable($tableName, $expectedResult)
+    {
+        $mainTableProperty = new \ReflectionProperty('Magento\Framework\Model\Resource\Db\AbstractDb', '_mainTable');
+        $mainTableProperty->setAccessible(true);
+        $mainTableProperty->setValue($this->_model, $tableName);
+        $this->_resourcesMock->expects($this->once())
+            ->method('getTableName')
+            ->with($expectedResult)
+            ->will($this->returnValue($expectedResult)
+            );
+        $this->assertEquals($expectedResult, $this->_model->getMainTable());
+    }
+
+    public function getTableDataProvider()
+    {
+        return [
+            [
+                'tableName',
+                'tableName'
+            ],
+            [
+                [
+                    'tableName',
+                    'entity_suffix'
+                ],
+                'tableName_entity_suffix'
+            ]
+        ];
+    }
+
+    public function testGetTable()
+    {
+        $data = 'tableName';
+        $this->_resourcesMock->expects($this->once())->method('getTableName')->with($data)->will(
+            $this->returnValue('tableName')
+        );
+        $tablesProperty = new \ReflectionProperty('Magento\Framework\Model\Resource\Db\AbstractDb', '_tables');
+        $tablesProperty->setAccessible(true);
+        $tablesProperty->setValue($this->_model, [$data]);
+        $this->assertEquals($data, $this->_model->getTable($data));
+    }
+
+    public function testGetChecksumNegative()
+    {
+        $this->assertEquals(false, $this->_model->getChecksum(null));
+    }
+
+    /**
+     * @dataProvider getChecksumProvider
+     * @param $checksum
+     * @param $expected
+     */
+    public function testGetChecksum($checksum, $expected)
+    {
+        $adapterInterfaceMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $adapterInterfaceMock->expects($this->once())->method('getTablesChecksum')->with($checksum)->will(
+            $this->returnValue([$checksum => 'checksum'])
+        );
+        $this->_resourcesMock->expects($this->any())->method('getConnection')->will(
+            $this->returnValue($adapterInterfaceMock)
+        );
+        $this->assertEquals($expected, $this->_model->getChecksum($checksum));
+    }
+
+    public function getChecksumProvider()
+    {
+        return [
+            [
+                'checksum',
+                'checksum'
+            ],
+            [
+                14,
+                'checksum'
+            ]
+        ];
+    }
+
+    public function testResetUniqueField()
+    {
+        $uniqueFields = new \ReflectionProperty('Magento\Framework\Model\Resource\Db\AbstractDb', '_uniqueFields');
+        $uniqueFields->setAccessible(true);
+        $uniqueFields->setValue($this->_model, ['uniqueField1', 'uniqueField2']);
+        $this->_model->resetUniqueField();
+        $this->assertEquals([], $this->_model->getUniqueFields());
+    }
+
+    public function testGetUniqueFields()
+    {
+        $uniqueFieldsReflection = new \ReflectionProperty(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            '_uniqueFields'
+        );
+        $uniqueFieldsReflection->setAccessible(true);
+        $uniqueFieldsReflection->setValue($this->_model, null);
+        $this->assertEquals([], $this->_model->getUniqueFields());
+    }
+
+    public function testGetValidationRulesBeforeSave()
+    {
+        $this->assertNull($this->_model->getValidationRulesBeforeSave());
+    }
+
+    public function testGetReadConnection()
+    {
+        $adapterInterfaceMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $this->_resourcesMock->expects($this->any())->method('getConnection')->will(
+            $this->returnValue($adapterInterfaceMock)
+        );
+        $this->assertInstanceOf('\Magento\Framework\DB\Adapter\AdapterInterface', $this->_model->getReadConnection());
+    }
+
+    public function testGetReadAdapter()
+    {
+        $adapterInterfaceMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $adapterInterfaceMock->expects($this->once())->method('getTransactionLevel')->will($this->returnValue(1));
+        $this->_resourcesMock->expects($this->any())->method('getConnection')->will(
+            $this->returnValue($adapterInterfaceMock)
+        );
+        $this->assertInstanceOf('\Magento\Framework\DB\Adapter\AdapterInterface', $this->_model->getReadConnection());
+    }
+
+    public function testLoad()
+    {
+        $contextMock = $this->getMock('\Magento\Framework\Model\Context', [], [], '', false);
+        $registryMock = $this->getMock('\Magento\Framework\Registry', [], [], '', false);
+        $abstractModelMock = $this->getMockForAbstractClass(
+            '\Magento\Framework\Model\AbstractModel',
+            [$contextMock, $registryMock],
+            '',
+            false,
+            true,
+            true,
+            ['__wakeup']
+        );
+
+        $value = 'some_value';
+        $idFieldName = new \ReflectionProperty('Magento\Framework\Model\Resource\Db\AbstractDb', '_idFieldName');
+        $idFieldName->setAccessible(true);
+        $idFieldName->setValue($this->_model, 'field_value');
+
+        $this->assertInstanceOf(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            $this->_model->load($abstractModelMock, $value, $idFieldName)
+        );
+    }
+
+    public function testDelete()
+    {
+        $adapterInterfaceMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $contextMock = $this->getMock('\Magento\Framework\Model\Context', [], [], '', false);
+        $registryMock = $this->getMock('\Magento\Framework\Registry', [], [], '', false);
+        $abstractModelMock = $this->getMockForAbstractClass(
+            '\Magento\Framework\Model\AbstractModel',
+            [$contextMock, $registryMock],
+            '',
+            false,
+            true,
+            true,
+            ['__wakeup', 'getId']
+        );
+        $this->_resourcesMock->expects($this->any())
+            ->method('getConnection')
+            ->will($this->returnValue($adapterInterfaceMock)
+        );
+        $data = 'tableName';
+        $this->_resourcesMock->expects($this->any())->method('getTableName')->with($data)->will(
+            $this->returnValue('tableName')
+        );
+        $mainTableReflection = new \ReflectionProperty(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            '_mainTable'
+        );
+        $mainTableReflection->setAccessible(true);
+        $mainTableReflection->setValue($this->_model, 'tableName');
+        $idFieldNameReflection = new \ReflectionProperty(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            '_idFieldName'
+        );
+        $idFieldNameReflection->setAccessible(true);
+        $idFieldNameReflection->setValue($this->_model, 'idFieldName');
+        $adapterInterfaceMock->expects($this->any())->method('delete')->with('tableName', 'idFieldName');
+        $adapterInterfaceMock->expects($this->any())->method('quoteInto')->will($this->returnValue('idFieldName'));
+        $this->assertInstanceOf(
+            'Magento\Framework\Model\Resource\Db\AbstractDb',
+            $this->_model->delete($abstractModelMock)
+        );
+    }
+
+    public function testHasDataChangedNegative()
+    {
+        $contextMock = $this->getMock('\Magento\Framework\Model\Context', [], [], '', false);
+        $registryMock = $this->getMock('\Magento\Framework\Registry', [], [], '', false);
+        $abstractModelMock = $this->getMockForAbstractClass(
+            '\Magento\Framework\Model\AbstractModel',
+            [$contextMock, $registryMock],
+            '',
+            false,
+            true,
+            true,
+            ['__wakeup', 'getOrigData']
+        );
+        $abstractModelMock->expects($this->any())->method('getOrigData')->will($this->returnValue(false));
+        $this->assertTrue($this->_model->hasDataChanged($abstractModelMock));
+    }
+
+    /**
+     * @dataProvider hasDataChangedDataProvider
+     * @param string $getOriginData
+     * @param bool $expected
+     */
+    public function testGetDataChanged($getOriginData, $expected)
+    {
+        $adapterInterfaceMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $this->_resourcesMock->expects($this->any())->method('getConnection')->will(
+            $this->returnValue($adapterInterfaceMock)
+        );
+        $contextMock = $this->getMock('\Magento\Framework\Model\Context', [], [], '', false);
+        $registryMock = $this->getMock('\Magento\Framework\Registry', [], [], '', false);
+        $abstractModelMock = $this->getMockForAbstractClass(
+            '\Magento\Framework\Model\AbstractModel',
+            [$contextMock, $registryMock],
+            '',
+            false,
+            true,
+            true,
+            ['__wakeup', 'getOrigData', 'getData']
+        );
+        $mainTableProperty = new \ReflectionProperty('Magento\Framework\Model\Resource\Db\AbstractDb', '_mainTable');
+        $mainTableProperty->setAccessible(true);
+        $mainTableProperty->setValue($this->_model, 'table');
+
+        $this->_resourcesMock->expects($this->once())
+            ->method('getTableName')
+            ->with('table')
+            ->will($this->returnValue('tableName')
+            );
+        $abstractModelMock->expects($this->at(0))->method('getOrigData')->will($this->returnValue(true));
+        $abstractModelMock->expects($this->at(1))->method('getOrigData')->will($this->returnValue($getOriginData));
+        $adapterInterfaceMock->expects($this->any())->method('describeTable')->with('tableName')->will(
+            $this->returnValue(['tableName'])
+        );
+        $this->assertEquals($expected, $this->_model->hasDataChanged($abstractModelMock));
+    }
+
+    public function hasDataChangedDataProvider()
+    {
+        return [
+            [true, true],
+            [null, 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
new file mode 100644
index 00000000000..4b5656f3ae3
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Framework/Model/Resource/Db/Collection/AbstractCollectionTest.php
@@ -0,0 +1,437 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Model\Resource\Db\Collection;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Framework\Object as MagentoObject;
+
+class AbstractCollectionTest extends \PHPUnit_Framework_TestCase
+{
+    const TABLE_NAME = 'some_table';
+
+    /** @var Uut */
+    protected $uut;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\Data\Collection\EntityFactoryInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $entityFactoryMock;
+
+    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    protected $loggerMock;
+
+    /** @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $fetchStrategyMock;
+
+    /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $managerMock;
+
+    /** @var \Magento\Framework\Model\Resource\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $resourceMock;
+
+    /** @var \Zend_Db_Adapter_Abstract|\PHPUnit_Framework_MockObject_MockObject */
+    protected $connectionMock;
+
+    /** @var \Zend_Db_Select|\PHPUnit_Framework_MockObject_MockObject  */
+    protected $selectMock;
+
+    /** @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */
+    protected $objectManagerMock;
+
+    protected function setUp()
+    {
+        $this->entityFactoryMock = $this->getMock('Magento\Framework\Data\Collection\EntityFactoryInterface');
+        $this->loggerMock = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $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);
+        $this->resourceMock = $this->getMock('Magento\Framework\Flag\Resource', [], [], '', false);
+
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getReadConnection')
+            ->will($this->returnValue($this->connectionMock));
+
+        $this->selectMock = $this->getMock(
+            'Zend_Db_Select',
+            ['getPart', 'setPart', 'from', 'columns'],
+            [$this->connectionMock]
+        );
+
+        $this->connectionMock
+            ->expects($this->any())
+            ->method('select')
+            ->will($this->returnValue($this->selectMock));
+
+        $this->objectManagerMock = $this->getMock('Magento\Framework\App\ObjectManager', [], [], '', false);
+        \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerMock);
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->uut = $this->getUut();
+    }
+
+    protected function getUut()
+    {
+        return $this->objectManagerHelper->getObject(
+            'Magento\Framework\Model\Resource\Db\Collection\Uut',
+            [
+                'entityFactory' => $this->entityFactoryMock,
+                'logger' => $this->loggerMock,
+                'fetchStrategy' => $this->fetchStrategyMock,
+                'eventManager' => $this->managerMock,
+                // Magento\Framework\DB\Adapter\Pdo\Mysql extends Zend_Db_Adapter_Abstract
+                'connection' => $this->connectionMock,
+                // Magento\Framework\Flag\Resource extends Magento\Framework\Model\Resource\Db\AbstractDb
+                'resource' => $this->resourceMock,
+            ]
+        );
+    }
+
+    public function testSetMainTableNull()
+    {
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getMainTable')
+            ->will($this->returnValue(null));
+
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getTable')
+            ->will($this->returnValue(null));
+
+        $this->uut = $this->getUut();
+
+        $this->assertTrue($this->uut->setMainTable('') instanceof Uut);
+        $this->assertEquals(null, $this->uut->getMainTable());
+    }
+
+    public function testSetMainTableFirst()
+    {
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getTable')
+            ->will($this->returnValue(self::TABLE_NAME));
+
+        $this->selectMock->expects($this->never())->method('getPart');
+
+        $this->assertTrue($this->uut->setMainTable('') instanceof Uut);
+        $this->assertEquals(self::TABLE_NAME, $this->uut->getMainTable());
+    }
+
+    public function testSetMainTableNoSelect()
+    {
+        $this->connectionMock
+            ->expects($this->any())
+            ->method('select')
+            ->will($this->returnValue(null));
+
+        $this->uut = $this->getUut();
+
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getTable')
+            ->will($this->returnValue(self::TABLE_NAME));
+
+        $this->uut->setMainTable('');
+        $this->selectMock->expects($this->never())->method('getPart');
+
+        $this->assertTrue($this->uut->setMainTable('') instanceof Uut);
+        $this->assertEquals(self::TABLE_NAME, $this->uut->getMainTable());
+    }
+
+    public function testSetMainTable()
+    {
+        $anotherTableName = 'another_table';
+
+        $this->selectMock
+            ->expects($this->atLeastOnce())
+            ->method('getPart')
+            ->will($this->returnValue(['main_table' => '']));
+
+        $this->selectMock->expects($this->atLeastOnce())->method('setPart');
+
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getTable')
+            ->will($this->returnValueMap([['', self::TABLE_NAME], [$anotherTableName, $anotherTableName]]));
+
+        $this->uut = $this->getUut();
+
+        $this->assertTrue($this->uut->setMainTable('') instanceof Uut);
+        $this->assertTrue($this->uut->setMainTable($anotherTableName) instanceof Uut);
+        $this->assertEquals($anotherTableName, $this->uut->getMainTable());
+    }
+
+    public function testGetSelectCached()
+    {
+        $this->selectMock
+            ->expects($this->never())
+            ->method('getPart');
+
+        $this->assertTrue($this->uut->getSelect() instanceof \Zend_Db_Select);
+    }
+
+    /**
+     * @dataProvider getSelectDataProvider
+     */
+    public function testGetSelect($idFieldNameRet, $getPartRet, $expected)
+    {
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getIdFieldName')
+            ->will($this->returnValue($idFieldNameRet));
+
+        $this->uut->removeAllFieldsFromSelect();
+
+        $this->selectMock
+            ->expects($this->any())
+            ->method('getPart')
+            ->will($this->returnValue($getPartRet));
+
+        $this->selectMock->expects($this->once())->method('setPart')->with(\Zend_Db_Select::COLUMNS, $expected);
+        $this->assertTrue($this->uut->getSelect() instanceof \Zend_Db_Select);
+    }
+
+    public function getSelectDataProvider()
+    {
+        $columnMock = $this->getMock('Zend_Db_Expr', ['__toString'], [], '', false);
+
+        return [
+            [
+                ['column_alias' => $columnMock],
+                [['correlation', $columnMock, 'alias']],
+                [
+                    ['main_table', ['column_alias' => $columnMock], null],
+                    'alias' => ['correlation', $columnMock, 'alias']
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * @dataProvider addFieldToSelectDataProvider
+     */
+    public function testAddFieldToSelect($field, $alias, $expectedFieldsToSelect)
+    {
+        $this->assertTrue($this->uut->addFieldToSelect($field, $alias) instanceof Uut);
+        $this->assertEquals($expectedFieldsToSelect, $this->uut->getFieldsToSelect());
+        $this->assertTrue($this->uut->wereFieldsToSelectChanged());
+    }
+
+    public function addFieldToSelectDataProvider()
+    {
+        return [
+            ['*', null, null],
+            [['alias' => 'column', 1 => 'column2'], null, ['alias' => 'column', 'column2']],
+            ['some_field', null, ['some_field']],
+            ['some_field', 'alias', ['alias' => 'some_field']]
+        ];
+    }
+
+    /**
+     * @dataProvider addExpressionFieldToSelectDataProvider
+     */
+    public function testAddExpressionFieldToSelect($alias, $expression, $fields, $expected)
+    {
+        $this->selectMock->expects($this->once())->method('columns')->with($expected);
+        $this->assertTrue($this->uut->addExpressionFieldToSelect($alias, $expression, $fields) instanceof Uut);
+    }
+
+    public function addExpressionFieldToSelectDataProvider()
+    {
+        return [
+            ['alias', '', 'some_field', ['alias' => '']],
+            ['alias', 'SUM({{var}})', ['var' => 'some_field'], ['alias' => 'SUM(some_field)']]
+        ];
+    }
+
+    /**
+     * @dataProvider removeFieldFromSelectDataProvider
+     */
+    public function testRemoveFieldFromSelect(
+        $field,
+        $isAlias,
+        $initialFieldsToSelect,
+        $expectedFieldsToSelect,
+        $expectedWereFieldsToSelectChanged
+    ) {
+        $this->uut->setFieldsToSelect($initialFieldsToSelect);
+        $this->assertTrue($this->uut->removeFieldFromSelect($field, $isAlias) instanceof Uut);
+        $this->assertEquals($expectedFieldsToSelect, $this->uut->getFieldsToSelect());
+        $this->assertEquals($expectedWereFieldsToSelectChanged, $this->uut->wereFieldsToSelectChanged());
+    }
+
+    public function removeFieldFromSelectDataProvider()
+    {
+        return [
+            ['some_field', false, [], [], false],
+            ['field_to_remove', false, ['field_to_remove' => 'field_name'], ['field_to_remove' => 'field_name'], false],
+            ['field_to_remove', true, ['field_to_remove' => 'field_name'], [], true],
+            ['r', false, ['a' => 'r', 'b' => 'c'], ['b' => 'c'], true]
+        ];
+    }
+
+    public function testRemoveAllFieldsFromSelect()
+    {
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getIdFieldName')
+            ->will($this->returnValue('id_field'));
+
+        $this->uut->setFieldsToSelect(['alias' => 'field']);
+        $this->assertTrue($this->uut->removeAllFieldsFromSelect() instanceof Uut);
+        $this->assertTrue($this->uut->wereFieldsToSelectChanged());
+        $this->assertEquals(['id_field'], $this->uut->getFieldsToSelect());
+    }
+
+    public function testSetModelNotString()
+    {
+        $this->assertTrue($this->uut->setModel(1) instanceof Uut);
+        $this->assertEmpty($this->uut->getModelName());
+    }
+
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Zend_Db_Select does not extend \Magento\Framework\Object
+     */
+    public function testSetModelInvalidType()
+    {
+        $this->uut->setModel('Zend_Db_Select');
+    }
+
+    public function testSetModel()
+    {
+        $this->assertTrue($this->uut->setModel('Magento\Framework\Object') instanceof Uut);
+    }
+
+    public function testGetModelName()
+    {
+        $this->uut->setModel('Magento\Framework\Object');
+        $this->assertEquals('Magento\Framework\Object', $this->uut->getModelName());
+    }
+
+    public function testGetResourceModelName()
+    {
+        $this->uut->setResourceModel('string');
+        $this->assertEquals('string', $this->uut->getResourceModelName());
+    }
+
+    public function testGetResource()
+    {
+        $this->objectManagerMock->expects($this->once())->method('create');
+        $this->uut->setResource(null);
+        $this->uut->getResource();
+    }
+
+    public function testGetResourceCached()
+    {
+        $this->objectManagerMock->expects($this->never())->method('create');
+        $this->uut->getResource();
+    }
+
+    public function testGetTable()
+    {
+        $this->resourceMock
+            ->expects($this->any())
+            ->method('getTable')
+            ->will($this->returnValue(self::TABLE_NAME));
+
+        $this->assertEquals(self::TABLE_NAME, $this->uut->getTable(''));
+    }
+
+    /**
+     * @dataProvider joinDataProvider
+     */
+    public function testJoin($table, $cond, $cols, $expected)
+    {
+        $this->assertTrue($this->uut->join($table, $cond, $cols) instanceof Uut);
+        $this->assertEquals($expected, $this->uut->getJoinedTables());
+    }
+
+    public function joinDataProvider()
+    {
+        return [
+            ['table', '', '*', ['table' => true]],
+            [['alias' => 'table'], '', '*', ['alias' => true]]
+        ];
+    }
+
+    public function testResetItemsDataChanged()
+    {
+        for ($i = 0; $i < 3; $i++) {
+            $this->uut->addItem((new MagentoObject())->setDataChanges(true));
+        }
+
+        $this->assertTrue($this->uut->resetItemsDataChanged() instanceof Uut);
+
+        foreach ($this->uut->getItems() as $item) {
+            $this->assertFalse($item->hasDataChanges());
+        }
+    }
+
+    public function testSave()
+    {
+        for ($i = 0; $i < 3; $i++) {
+            /** @var \Magento\Framework\Object|\PHPUnit_Framework_MockObject_MockObject $item */
+            $item = $this->getMock('Magento\Framework\Object', ['save']);
+            $item->expects($this->once())->method('save');
+            $this->uut->addItem($item);
+        }
+
+        $this->assertTrue($this->uut->save() instanceof Uut);
+    }
+}
+
+/**
+ * Pattern type: Public Morozov
+ */
+class Uut extends AbstractCollection
+{
+    public function wereFieldsToSelectChanged()
+    {
+        return $this->_fieldsToSelectChanged;
+    }
+
+    public function getFieldsToSelect()
+    {
+        return $this->_fieldsToSelect;
+    }
+
+    public function setFieldsToSelect(array $fields)
+    {
+        $this->_fieldsToSelect = $fields;
+    }
+
+    public function setResource($resource)
+    {
+        $this->_resource = $resource;
+    }
+
+    public function getJoinedTables()
+    {
+        return $this->_joinedTables;
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/DomTest.php b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/DomTest.php
index d5d149bd338..6bb60feaec8 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/DomTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/DomTest.php
@@ -64,18 +64,18 @@ class DomTest extends \PHPUnit_Framework_TestCase
                 '<?xml version="1.0"?><config><module name="Module_One" /></config>'
             ),
             'Module node without "active" attribute' => array(
-                '<?xml version="1.0"?><config><module name="Module_One" version="1.0.0.0" /></config>'
+                '<?xml version="1.0"?><config><module name="Module_One" schema_version="1.0.0.0" /></config>'
             ),
             'Dependency module node without "name" attribute' => array(
-                '<?xml version="1.0"?><config><module name="Module_One" version="1.0.0.0" active="true">' .
+                '<?xml dbversion="1.0"?><config><module name="Module_One" schema_version="1.0.0.0" active="true">' .
                 '<sequence><module/></sequence></module></config>'
             ),
             'Dependency extension node without "name" attribute' => array(
-                '<?xml version="1.0"?><config><module name="Module_One" version="1.0.0.0" active="true">' .
+                '<?xml dbversion="1.0"?><config><module name="Module_One" schema_version="1.0.0.0" active="true">' .
                 '<depends><extension/></depends></module></config>'
             ),
             'Empty choice node' => array(
-                '<?xml version="1.0"?><config><module name="Module_One" version="1.0.0.0" active="true">' .
+                '<?xml dbversion="1.0"?><config><module name="Module_One" schema_version="1.0.0.0" active="true">' .
                 '<depends><choice/></depends></module></config>'
             )
         );
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/converted_valid_module.php b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/converted_valid_module.php
index f1b48c386e1..a5a3dfc6ccd 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/converted_valid_module.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/converted_valid_module.php
@@ -24,7 +24,7 @@
 return array(
     'Module_One' => array(
         'name' => 'Module_One',
-        'version' => '1.0.0.0',
+        'schema_version' => '1.0.0.0',
         'active' => true,
         'dependencies' => array(
             'modules' => array(),
@@ -38,7 +38,7 @@ return array(
     ),
     'Module_Two' => array(
         'name' => 'Module_Two',
-        'version' => '2.0.0.0',
+        'schema_version' => '2.0.0.0',
         'active' => false,
         'dependencies' => array(
             'modules' => array('Module_One'),
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/valid_module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/valid_module.xml
index b0628d9abae..1eb34c48ba1 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/valid_module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Converter/_files/valid_module.xml
@@ -23,9 +23,9 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
     <!-- commented text -->
-    <module name="Module_One" version="1.0.0.0" active="true">
+    <module name="Module_One" schema_version="1.0.0.0" active="true">
         <depends>
             <!-- commented text -->
             <extension name="spl" />
@@ -36,7 +36,7 @@
             </choice>
         </depends>
     </module>
-    <module name="Module_Two" version="2.0.0.0" active="false">
+    <module name="Module_Two" schema_version="2.0.0.0" active="false">
         <sequence>
             <module name="Module_One" />
         </sequence>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Four/etc/module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Four/etc/module.xml
index a3d326edefb..cb3005c5b3b 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Four/etc/module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Four/etc/module.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Module_Four" version="1.0.0.0" active="true">
+    <module name="Module_Four" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Module_One" />
         </sequence>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/One/etc/module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/One/etc/module.xml
index 6c852b57fc7..6125ef5cba1 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/One/etc/module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/One/etc/module.xml
@@ -23,8 +23,8 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Module_One" version="1.0.0.0" active="true">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Module_One" schema_version="1.0.0.0" active="true">
         <depends>
             <choice>
                 <extension name="gd" />
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Three/etc/module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Three/etc/module.xml
index 15ca36f67b5..7d66ec36236 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Three/etc/module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Three/etc/module.xml
@@ -23,8 +23,8 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Module_Three" version="1.0.0.0" active="true">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Module_Three" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Module_Four" />
         </sequence>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Two/etc/module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Two/etc/module.xml
index b9feb6d62fa..5d67c848804 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Two/etc/module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/code/Module/Two/etc/module.xml
@@ -23,8 +23,8 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
-    <module name="Module_Two" version="1.0.0.0" active="true">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+    <module name="Module_Two" schema_version="1.0.0.0" active="true">
         <sequence>
             <module name="Module_One" />
         </sequence>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/etc/custom/module.xml b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/etc/custom/module.xml
index 6905561e865..f918c432ef8 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/etc/custom/module.xml
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/FileResolver/_files/app/etc/custom/module.xml
@@ -23,7 +23,7 @@
  * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
  */
 -->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
     <module name="Module_One" active="true" />
     <module name="Module_Two" active="false" />
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Reader/FilesystemTest.php b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Reader/FilesystemTest.php
index 8e40d7cd688..ad681ab3427 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Reader/FilesystemTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/Module/Declaration/Reader/FilesystemTest.php
@@ -70,7 +70,7 @@ class FilesystemTest extends \PHPUnit_Framework_TestCase
         $expectedResult = array(
             'Module_One' => array(
                 'name' => 'Module_One',
-                'version' => '1.0.0.0',
+                'schema_version' => '1.0.0.0',
                 'active' => true,
                 'dependencies' => array(
                     'modules' => array(),
@@ -84,7 +84,7 @@ class FilesystemTest extends \PHPUnit_Framework_TestCase
             ),
             'Module_Four' => array(
                 'name' => 'Module_Four',
-                'version' => '1.0.0.0',
+                'schema_version' => '1.0.0.0',
                 'active' => true,
                 'dependencies' => array(
                     'modules' => array('Module_One'),
@@ -93,7 +93,7 @@ class FilesystemTest extends \PHPUnit_Framework_TestCase
             ),
             'Module_Three' => array(
                 'name' => 'Module_Three',
-                'version' => '1.0.0.0',
+                'schema_version' => '1.0.0.0',
                 'active' => true,
                 'dependencies' => array(
                     'modules' => array('Module_Four'),
diff --git a/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php b/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
index 56ffb6e2186..2301ef7bb2c 100644
--- a/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
+++ b/dev/tests/unit/testsuite/Magento/Framework/TranslateTest.php
@@ -36,9 +36,6 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\View\DesignInterface */
     protected $_viewDesign;
 
-    /** @var \Magento\Framework\Locale\Hierarchy\Config */
-    protected $_config;
-
     /** @var \Magento\Framework\Cache\FrontendInterface */
     protected $_cache;
 
@@ -72,13 +69,15 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Framework\File\Csv */
     protected $_csvParser;
 
+    /** @var  \Magento\Framework\App\Language\Dictionary|\PHPUnit_Framework_MockObject_MockObject */
+    protected $_packDictionary;
+
     /** @var \Magento\Framework\Filesystem\Directory\ReadInterface */
     protected $_directory;
 
     public function setUp()
     {
         $this->_viewDesign = $this->getMock('\Magento\Framework\View\DesignInterface', [], [], '', false);
-        $this->_config = $this->getMock('\Magento\Framework\Locale\Hierarchy\Config', [], [], '', false);
         $this->_cache = $this->getMock('\Magento\Framework\Cache\FrontendInterface', [], [], '', false);
         $this->_viewFileSystem = $this->getMock('\Magento\Framework\View\FileSystem', [], [], '', false);
         $this->_moduleList = $this->getMock('\Magento\Framework\Module\ModuleList', [], [], '', false);
@@ -89,16 +88,13 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
         $this->_appState = $this->getMock('\Magento\Framework\App\State', [], [], '', false);
         $this->_request = $this->getMock('\Magento\Framework\App\RequestInterface', [], [], '', false);
         $this->_csvParser = $this->getMock('\Magento\Framework\File\Csv', [], [], '', false);
-        $this->_config->expects($this->once())
-            ->method('getHierarchy')
-            ->will($this->returnValue(['en_US' => ['en_GB']]));
+        $this->_packDictionary = $this->getMock('\Magento\Framework\App\Language\Dictionary', [], [], '', false);
         $this->_directory = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface', [], [], '', false);
         $filesystem = $this->getMock('\Magento\Framework\App\Filesystem', [], [], '', false);
         $filesystem->expects($this->once())->method('getDirectoryRead')->will($this->returnValue($this->_directory));
 
         $this->_translate = new Translate(
             $this->_viewDesign,
-            $this->_config,
             $this->_cache,
             $this->_viewFileSystem,
             $this->_moduleList,
@@ -109,7 +105,8 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
             $this->_appState,
             $filesystem,
             $this->_request,
-            $this->_csvParser
+            $this->_csvParser,
+            $this->_packDictionary
         );
     }
 
@@ -162,6 +159,10 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
             ->method('getLocaleFileName')
             ->will($this->returnValue('/theme.csv'));
 
+        // _loadPackTranslation
+        $packData = ['pack original' => 'pack translated'];
+        $this->_packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue($packData));
+
         // _loadDbTranslation()
         $dbData = ['db original' => 'db translated'];
         $this->_resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue($dbData));
@@ -171,11 +172,11 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
 
         $this->_translate->loadData($area, $forceReload);
 
-        $condition = ($area == 'adminhtml' && !$forceReload) ? true : false;
         $expected = [
             'module original' => 'module translated',
-            ($condition ? 'themethemeId::' : '') . 'theme original' => 'theme translated',
-            ($condition ? 'adminCode::' : '') . 'db original' => 'db translated'
+            'theme original' => 'theme translated',
+            'pack original' => 'pack translated',
+            'db original' => 'db translated'
         ];
         $this->assertEquals($expected, $this->_translate->getData());
     }
@@ -256,6 +257,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
         $this->_expectsSetConfig(null, null);
         $this->_moduleList->expects($this->once())->method('getModules')->will($this->returnValue([]));
         $this->_appState->expects($this->once())->method('getAreaCode')->will($this->returnValue('frontend'));
+        $this->_packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue([]));
         $this->_resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue([]));
         $this->assertEquals($this->_translate, $this->_translate->loadData(null, $forceReload));
     }
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.php
index 67a2dd20c15..4b7301e972d 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.php
@@ -22,8 +22,28 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 return array(
-    'entities' => array('name_one' => array('name' => 'name_one', 'label' => 'Label_One', 'model' => 'Model_One')),
-    'productTypes' => array('name_two' => array('name' => 'name_two', 'model' => 'Model_Two')),
+    'entities' => array(
+        'product' => array(
+            'name' => 'product',
+            'label' => 'Label_One',
+            'model' => 'Model_One',
+            'types' => array(
+                'product_type_one' => array('name' => 'product_type_one', 'model' => 'Product_Model_Type_One'),
+                'type_two' => array('name' => 'type_two', 'model' => 'Model_Type_Two')
+            ),
+            'entityAttributeFilterType' => 'product'
+        ),
+        'customer' => array(
+            'name' => 'customer',
+            'label' => 'Label_One',
+            'model' => 'Model_One',
+            'types' => array(
+                'type_one' => array('name' => 'type_one', 'model' => 'Model_Type_One'),
+                'type_two' => array('name' => 'type_two', 'model' => 'Model_Type_Two')
+            ),
+            'entityAttributeFilterType' => 'customer'
+        )
+    ),
     'fileFormats' => array(
         'name_three' => array('name' => 'name_three', 'model' => 'Model_Three', 'label' => 'Label_Three')
     )
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.xml b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.xml
index 60c07c5d12b..33c2080bc1a 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.xml
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export.xml
@@ -24,7 +24,11 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/ImportExport/etc/export.xsd">
-    <entity name="name_one" label="Label_One" model="Model_One" />
-    <productType name="name_two" model="Model_Two" />
+    <entity name="product" label="Label_One" model="Model_One" entityAttributeFilterType="product"/>
+    <entity name="customer" label="Label_One" model="Model_One" entityAttributeFilterType="customer"/>
+    <entityType entity="customer" name="type_one" model="Model_Type_One" />
+    <entityType entity="customer" name="type_two" model="Model_Type_Two" />
+    <entityType entity="product" name="product_type_one" model="Product_Model_Type_One" />
+    <entityType entity="product" name="type_two" model="Model_Type_Two" />
     <fileFormat name="name_three" label="Label_Three" model="Model_Three" />
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_merged_valid.xml b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_merged_valid.xml
index 232a530b380..bbba2600882 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_merged_valid.xml
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_merged_valid.xml
@@ -24,7 +24,7 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/ImportExport/etc/export_merged.xsd">
-    <entity name="Entity_Name" label="Label_One" model="Model_One" />
-    <productType name="productType_Name" model="Model_Two" />
+    <entity name="Entity_Name" label="Label_One" model="Model_One" entityAttributeFilterType="Entity_Name" />
+    <entityType entity="Entity_Name" name="productType_Name" model="Model_Two" />
     <fileFormat name="file_Name" label="Label_Three" model="Model_Three" />
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_valid.xml b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_valid.xml
index ba968864df8..b0b21d7c089 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_valid.xml
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/export_valid.xml
@@ -24,9 +24,9 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/ImportExport/etc/export.xsd">
-    <entity name="name_one" label="Label_One" model="Model_One" />
-    <entity name="name_two" />
-    <productType name="name_two" model="Model_Two" />
+    <entity name="name_one" label="Label_One" model="Model_One" entityAttributeFilterType="name_one"/>
+    <entity name="name_two" entityAttributeFilterType="name_two"/>
+    <entityType entity="name_one" name="name_two" model="Model_Two" />
     <fileFormat name="name_three" label="Label_Three" model="Model_Three" />
     <fileFormat name="file_name" />
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportMergedXmlArray.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportMergedXmlArray.php
index 1fcd5173798..686c1d022ba 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportMergedXmlArray.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportMergedXmlArray.php
@@ -32,12 +32,15 @@ return array(
         )
     ),
     'entity_node_with_required_attribute' => array(
-        '<?xml version="1.0"?><config><entity label="name_one" model="model"/><entity name="name_one" model="model"/>' .
-        '<entity label="name" name="model"/></config>',
+        '<?xml version="1.0"?><config><entity label="name_one" model="model" entityAttributeFilterType="name_one"/>' .
+        '<entity name="name_one" model="model" entityAttributeFilterType="name_two"/>' .
+        '<entity label="name" name="model" entityAttributeFilterType="name_three"/>' .
+        '<entity label="name" name="model_two" model="model"/></config>',
         array(
             "Element 'entity': The attribute 'name' is required but missing.",
             "Element 'entity': The attribute " . "'label' is required but missing.",
-            "Element 'entity': The attribute 'model' is required but missing."
+            "Element 'entity': The attribute 'model' is required but missing.",
+            "Element 'entity': The attribute 'entityAttributeFilterType' is required but missing."
         )
     )
 );
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportXmlArray.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportXmlArray.php
index e5538f3bd63..b5aa8ea17c9 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportXmlArray.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/Config/_files/invalidExportXmlArray.php
@@ -23,20 +23,13 @@
  */
 return array(
     'export_entity_name_must_be_unique' => array(
-        '<?xml version="1.0"?><config><entity name="name_one" /><entity name="name_one" /></config>',
+        '<?xml version="1.0"?><config><entity name="name_one" entityAttributeFilterType="name_one"/>'
+            . '<entity name="name_one" entityAttributeFilterType="name_one"/></config>',
         array(
             "Element 'entity': Duplicate key-sequence ['name_one'] in unique identity-constraint " .
             "'uniqueEntityName'."
         )
     ),
-    'export_productType_name_must_be_unique' => array(
-        '<?xml version="1.0"?><config><productType name="name_one" model="model"/><productType name="name_one" ' .
-        'model="model" /></config>',
-        array(
-            "Element 'productType': Duplicate key-sequence ['name_one'] in unique identity-constraint " .
-            "'uniqueProductTypeName'."
-        )
-    ),
     'export_fileFormat_name_must_be_unique' => array(
         '<?xml version="1.0"?><config><fileFormat name="name_one" /><fileFormat name="name_one" /></config>',
         array(
@@ -45,12 +38,13 @@ return array(
         )
     ),
     'attributes_with_type_modelName_and_invalid_value' => array(
-        '<?xml version="1.0"?><config><entity name="Name/one" model="model_one"/><productType name="name_one" ' .
-        ' model="1"/><fileFormat name="name_one" model="model1"/></config>',
+        '<?xml version="1.0"?><config><entity name="Name/one" model="model_one" '
+            . 'entityAttributeFilterType="model_one"/><entityType entity="Name/one" name="name_one" model="1"/>'
+            . ' <fileFormat name="name_one" model="model1"/></config>',
         array(
-            "Element 'productType', attribute 'model': [facet 'pattern'] The value '1' is not accepted by the " .
+            "Element 'entityType', attribute 'model': [facet 'pattern'] The value '1' is not accepted by the " .
             "pattern '[A-Za-z_\\\\\\\\]+'.",
-            "Element 'productType', attribute 'model': '1' is not a valid value of the atomic " . "type 'modelName'.",
+            "Element 'entityType', attribute 'model': '1' is not a valid value of the atomic " . "type 'modelName'.",
             "Element 'fileFormat', attribute 'model': [facet 'pattern'] The value 'model1' is not " .
             "accepted by the pattern '[A-Za-z_\\\\\\\\]+'.",
             "Element 'fileFormat', attribute 'model': 'model1' is not a valid " .
@@ -58,10 +52,11 @@ return array(
         )
     ),
     'productType_node_with_required_attribute' => array(
-        '<?xml version="1.0"?><config><productType name="name_one" /><productType model="model" /></config>',
+        '<?xml version="1.0"?><config><entityType entity="name_one" name="name_one" />'
+            . '<entityType entity="name_one" model="model" /></config>',
         array(
-            "Element 'productType': The attribute 'model' is required but missing.",
-            "Element 'productType': " . "The attribute 'name' is required but missing."
+            "Element 'entityType': The attribute 'model' is required but missing.",
+            "Element 'entityType': " . "The attribute 'name' is required but missing."
         )
     ),
     'fileFormat_node_with_required_attribute' => array(
@@ -69,7 +64,11 @@ return array(
         array("Element 'fileFormat': The attribute 'name' is required but missing.")
     ),
     'entity_node_with_required_attribute' => array(
-        '<?xml version="1.0"?><config><entity label="name_one" /></config>',
+        '<?xml version="1.0"?><config><entity label="name_one" entityAttributeFilterType="name_one"/></config>',
         array("Element 'entity': The attribute 'name' is required but missing.")
+    ),
+    'entity_node_with_missing_filter_type_attribute' => array(
+        '<?xml version="1.0"?><config><entity label="name_one" name="name_one"/></config>',
+        array("Element 'entity': The attribute 'entityAttributeFilterType' is required but missing.")
     )
 );
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/ConfigTest.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/ConfigTest.php
index 54af7a20c0d..e0fafa064f4 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Export/ConfigTest.php
@@ -91,11 +91,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @param array $value
-     * @param null|string $expected
-     * @dataProvider getProductTypesDataProvider
+     * @param array $configData
+     * @param string $entity
+     * @param string[] $expectedResult
+     * @dataProvider getEntityTypesDataProvider
      */
-    public function testGetProductTypes($value, $expected)
+    public function testGetEntityTypes($configData, $entity, $expectedResult)
     {
         $this->_configScopeMock->expects(
             $this->any()
@@ -106,21 +107,41 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         )->will(
             $this->returnValue(false)
         );
-        $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($value));
+        $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($configData));
         $this->_model = new \Magento\ImportExport\Model\Export\Config(
             $this->_readerMock,
             $this->_configScopeMock,
             $this->_cacheId
         );
-        $this->assertEquals($expected, $this->_model->getProductTypes('productTypes'));
+        $this->assertEquals($expectedResult, $this->_model->getEntityTypes($entity));
     }
 
-    public function getProductTypesDataProvider()
+    public function getEntityTypesDataProvider()
     {
-        return array(
-            'productTypes_key_exist' => array(array('productTypes' => 'value'), 'value'),
-            'return_default_value' => array(array('key_one' => 'value'), null)
-        );
+        return [
+            'valid type' => [
+                [
+                    'entities' => [
+                        'catalog_product' => [
+                            'types' => ['configurable', 'simple']
+                        ]
+                    ]
+                ],
+                'catalog_product',
+                ['configurable', 'simple']
+            ],
+            'not existing entity' => [
+                [
+                    'entities' => [
+                        'catalog_product' => [
+                            'types' => ['configurable', 'simple']
+                        ]
+                    ]
+                ],
+                'not existing entity',
+                []
+            ],
+        ];
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.php
index 623bfa6b18c..13a48f72cbe 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.php
@@ -23,12 +23,54 @@
  */
 return array(
     'entities' => array(
-        'name_one' => array(
-            'name' => 'name_one',
+        'product' => array(
+            'name' => 'product',
             'label' => 'Label_One',
             'behaviorModel' => 'Model_Basic',
-            'model' => 'Model_One'
-        )
-    ),
-    'productTypes' => array('name_two' => array('name' => 'name_two', 'model' => 'Model_Two'))
+            'model' => 'Model_One',
+            'types' =>
+                array(
+                    'product_type_one' => array(
+                        'name' => 'product_type_one',
+                        'model' => 'Product_Type_One',
+                    ),
+                    'type_two' => array(
+                        'name' => 'type_two',
+                        'model' => 'Product_Type_Two',
+                    ),
+                ),
+            'relatedIndexers' => array(
+                'simple_index' => array(
+                    'name' => 'simple_index',
+                ),
+                'custom_product_index' => array(
+                    'name' => 'custom_product_index',
+                ),
+            ),
+        ),
+        'customer' => array(
+            'name' => 'customer',
+            'label' => 'Label_One',
+            'behaviorModel' => 'Model_Basic',
+            'model' => 'Model_One',
+            'types' => array(
+                'customer_type_one' => array(
+                    'name' => 'customer_type_one',
+                    'model' => 'Customer_Type_One',
+                ),
+                'type_two' => array(
+                    'name' => 'type_two',
+                    'model' => 'Customer_Type_Two',
+                ),
+            ),
+            'relatedIndexers' => array(
+                'simple_index' => array(
+                    'name' => 'simple_index',
+                ),
+                'custom_customer_index' => array(
+                    'name' => 'custom_customer_index',
+                ),
+            ),
+        ),
+    )
 );
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.xml b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.xml
index 54a4b2fa123..0098dd10a6a 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.xml
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/import.xml
@@ -24,6 +24,14 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/ImportExport/etc/import.xsd">
-    <entity name="name_one" label="Label_One" model="Model_One" behaviorModel="Model_Basic" />
-    <productType name="name_two" model="Model_Two" />
+    <entity name="product" label="Label_One" model="Model_One" behaviorModel="Model_Basic" />
+    <entity name="customer" label="Label_One" model="Model_One" behaviorModel="Model_Basic" />
+    <entityType entity="customer" name="customer_type_one" model="Customer_Type_One" />
+    <entityType entity="customer" name="type_two" model="Customer_Type_Two" />
+    <entityType entity="product" name="product_type_one" model="Product_Type_One" />
+    <entityType entity="product" name="type_two" model="Product_Type_Two" />
+    <relatedIndexer entity="product" name="simple_index"/>
+    <relatedIndexer entity="product" name="custom_product_index"/>
+    <relatedIndexer entity="customer" name="simple_index"/>
+    <relatedIndexer entity="customer" name="custom_customer_index"/>
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/invalidImportXmlArray.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/invalidImportXmlArray.php
index 8df0dd42324..3a5a906504e 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/invalidImportXmlArray.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/invalidImportXmlArray.php
@@ -53,32 +53,25 @@ return array(
         '<?xml version="1.0"?><config><entity name="some_name" notallowd="aasd"/></config>',
         array("Element 'entity', attribute 'notallowd': The attribute 'notallowd' is not allowed.")
     ),
-    'producttype_with_same_name_attribute_value' => array(
-        '<?xml version="1.0"?><config><productType name="same_name" model="model_name" />' .
-        '<productType name="same_name" model="model_name" /></config>',
-        array(
-            "Element 'productType': Duplicate key-sequence ['same_name'] in unique " .
-            "identity-constraint 'uniqueProductTypeName'."
-        )
-    ),
-    'producttype_without_required_name_attribute' => array(
-        '<?xml version="1.0"?><config><productType model="model_name" /></config>',
-        array("Element 'productType': The attribute 'name' is required but missing.")
+    'entitytype_without_required_name_attribute' => array(
+        '<?xml version="1.0"?><config><entityType entity="entity_name" model="model_name" /></config>',
+        array("Element 'entityType': The attribute 'name' is required but missing.")
     ),
-    'producttype_without_required_model_attribute' => array(
-        '<?xml version="1.0"?><config><productType name="some_name" /></config>',
-        array("Element 'productType': The attribute 'model' is required but missing.")
+    'entitytype_without_required_model_attribute' => array(
+        '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" /></config>',
+        array("Element 'entityType': The attribute 'model' is required but missing.")
     ),
-    'producttype_with_invalid_model_attribute_value' => array(
-        '<?xml version="1.0"?><config><productType name="some_name" model="test1"/></config>',
+    'entitytype_with_invalid_model_attribute_value' => array(
+        '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" model="test1"/></config>',
         array(
-            "Element 'productType', attribute 'model': [facet 'pattern'] The value 'test1' is not " .
+            "Element 'entityType', attribute 'model': [facet 'pattern'] The value 'test1' is not " .
             "accepted by the pattern '[A-Za-z_\\\\\\\\]+'.",
-            "Element 'productType', attribute 'model': 'test1' is not a valid value of the atomic type 'modelName'."
+            "Element 'entityType', attribute 'model': 'test1' is not a valid value of the atomic type 'modelName'."
         )
     ),
-    'producttype_with_notallowed' => array(
-        '<?xml version="1.0"?><config><productType name="some_name" model="test" notallowed="test"/></config>',
-        array("Element 'productType', attribute 'notallowed': The attribute 'notallowed' is not allowed.")
+    'entitytype_with_notallowed' => array(
+        '<?xml version="1.0"?><config><entityType entity="entity_name" name="some_name" '
+            . 'model="test" notallowed="test"/></config>',
+        array("Element 'entityType', attribute 'notallowed': The attribute 'notallowed' is not allowed.")
     )
 );
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/valid_import.xml b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/valid_import.xml
index 17070dfe2be..c766b0b3056 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/valid_import.xml
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/Config/_files/valid_import.xml
@@ -25,5 +25,6 @@
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/ImportExport/etc/import.xsd">
     <entity name="test_name" label="Some Label" model="test_Model_name" behaviorModel="Test_value" />
-    <productType name="product_type" model="Test_Model_value" />
+    <entityType entity="test_name" name="product_type" model="Test_Model_value" />
+    <relatedIndexer entity="test_name" name="product_type" />
 </config>
diff --git a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/ConfigTest.php b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/ConfigTest.php
index 41937cad4ce..ef6cb3ab3da 100644
--- a/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/ImportExport/Model/Import/ConfigTest.php
@@ -91,11 +91,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @param array $value
-     * @param null|string $expected
-     * @dataProvider getProductTypesDataProvider
+     * @param array $configData
+     * @param string $entity
+     * @param string[] $expectedResult
+     * @dataProvider getEntityTypesDataProvider
      */
-    public function testGetProductTypes($value, $expected)
+    public function testGetEntityTypes($configData, $entity, $expectedResult)
     {
         $this->_configScopeMock->expects(
             $this->any()
@@ -106,20 +107,40 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         )->will(
             $this->returnValue(false)
         );
-        $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($value));
+        $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($configData));
         $this->_model = new \Magento\ImportExport\Model\Import\Config(
             $this->_readerMock,
             $this->_configScopeMock,
             $this->_cacheId
         );
-        $this->assertEquals($expected, $this->_model->getProductTypes('productTypes'));
+        $this->assertEquals($expectedResult, $this->_model->getEntityTypes($entity));
     }
 
-    public function getProductTypesDataProvider()
+    public function getEntityTypesDataProvider()
     {
-        return array(
-            'productTypes_key_exist' => array(array('productTypes' => 'value'), 'value'),
-            'return_default_value' => array(array('key_one' => 'value'), null)
-        );
+        return [
+            'valid type' => [
+                [
+                    'entities' => [
+                        'catalog_product' => [
+                            'types' => ['configurable', 'simple']
+                        ]
+                    ]
+                ],
+                'catalog_product',
+                ['configurable', 'simple']
+            ],
+            'not existing entity' => [
+                [
+                    'entities' => [
+                        'catalog_product' => [
+                            'types' => ['configurable', 'simple']
+                        ]
+                    ]
+                ],
+                'not existing entity',
+                []
+            ],
+        ];
     }
 }
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 6a22a3a7f53..9bb9fe60207 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Controller/Adminhtml/IntegrationTest.php
@@ -62,10 +62,10 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject */
     protected $_backendActionCtxMock;
 
-    /** @var \Magento\Integration\Service\IntegrationV1|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Integration\Service\V1\Integration|\PHPUnit_Framework_MockObject_MockObject */
     protected $_integrationSvcMock;
 
-    /** @var \Magento\Integration\Service\OauthV1|\PHPUnit_Framework_MockObject_MockObject */
+    /** @var \Magento\Integration\Service\V1\Oauth|\PHPUnit_Framework_MockObject_MockObject */
     protected $_oauthSvcMock;
 
     /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */
@@ -130,10 +130,10 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase
             'Magento\Framework\TranslateInterface'
         )->disableOriginalConstructor()->getMock();
         $this->_integrationSvcMock = $this->getMockBuilder(
-            'Magento\Integration\Service\IntegrationV1'
+            'Magento\Integration\Service\V1\Integration'
         )->disableOriginalConstructor()->getMock();
         $this->_oauthSvcMock = $this->getMockBuilder(
-            'Magento\Integration\Service\OauthV1'
+            'Magento\Integration\Service\V1\Oauth'
         )->disableOriginalConstructor()->getMock();
         $this->_requestMock = $this->getMockBuilder(
             'Magento\Framework\App\Request\Http'
@@ -846,6 +846,7 @@ HANDLE;
         $this->_layoutMock->expects($this->any())->method('getMessagesBlock')->will($this->returnValue($blockMock));
         $this->_layoutMock->expects($this->any())->method('getBlock')->will($this->returnValue($blockMock));
         $this->_escaper->expects($this->any())->method('escapeHtml')->will($this->returnArgument(0));
+
         $contextParameters = array(
             'view' => $this->_viewMock,
             'objectManager' => $this->_objectManagerMock,
@@ -860,6 +861,18 @@ HANDLE;
             'Magento\Backend\App\Action\Context',
             $contextParameters
         );
+
+        $integrationCollection = $this->getMockBuilder('\Magento\Integration\Model\Resource\Integration\Collection')
+            ->disableOriginalConstructor()
+            ->setMethods(['addUnsecureEndpointFilter', 'getSize'])
+            ->getMock();
+        $integrationCollection->expects($this->any())
+            ->method('addUnsecureEndpointFilter')
+            ->will($this->returnValue($integrationCollection));
+        $integrationCollection->expects($this->any())
+            ->method('getSize')
+            ->will($this->returnValue(0));
+
         $subControllerParams = array(
             'context' => $this->_backendActionCtxMock,
             'integrationService' => $this->_integrationSvcMock,
@@ -867,7 +880,8 @@ HANDLE;
             'registry' => $this->_registryMock,
             'logger' => $loggerMock,
             'integrationData' => $this->_integrationHelperMock,
-            'escaper' => $this->_escaper
+            'escaper' => $this->_escaper,
+            'integrationCollection' => $integrationCollection
         );
         /** Create IntegrationController to test */
         $controller = $this->_objectManagerHelper->getObject(
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 c93edfc4ce1..e5c33c55864 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/ConsumerTest.php
@@ -49,7 +49,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Integration\Helper\Oauth\Data */
     protected $_dataHelper;
 
-    /** @var \Magento\Integration\Service\OauthV1Interface */
+    /** @var \Magento\Integration\Service\V1\OauthInterface */
     protected $_oauthService;
 
     /** @var \Magento\Framework\Logger */
@@ -114,7 +114,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase
             array('logException')
         )->getMock();
 
-        $this->_oauthService = new \Magento\Integration\Service\OauthV1(
+        $this->_oauthService = new \Magento\Integration\Service\V1\Oauth(
             $this->_storeManagerMock,
             $this->_consumerFactory,
             $this->_tokenFactory,
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/RequestTest.php b/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/RequestTest.php
index 8d9ea8832f9..371bab5f64e 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/RequestTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Helper/Oauth/RequestTest.php
@@ -25,8 +25,6 @@
  */
 namespace Magento\Integration\Helper\Oauth;
 
-use Magento\Framework\Oauth\OauthInterface;
-
 class RequestTest extends \PHPUnit_Framework_TestCase
 {
     /** @var \Magento\Framework\Oauth\Helper\Request */
@@ -57,25 +55,9 @@ class RequestTest extends \PHPUnit_Framework_TestCase
     {
         return array(
             array(
-                new \Magento\Framework\Oauth\Exception('msg', OauthInterface::ERR_VERSION_REJECTED),
-                new \Zend_Controller_Response_Http(),
-                array('version_rejected&message=msg', \Magento\Framework\Oauth\Helper\Request::HTTP_BAD_REQUEST)
-            ),
-            array(
-                new \Magento\Framework\Oauth\Exception('msg', 255),
-                new \Zend_Controller_Response_Http(),
-                array(
-                    'unknown_problem&code=255&message=msg',
-                    \Magento\Framework\Oauth\Helper\Request::HTTP_INTERNAL_ERROR
-                )
-            ),
-            array(
-                new \Magento\Framework\Oauth\Exception('param', OauthInterface::ERR_PARAMETER_ABSENT),
+                new \Magento\Framework\Oauth\OauthInputException('msg'),
                 new \Zend_Controller_Response_Http(),
-                array(
-                    'parameter_absent&oauth_parameters_absent=param',
-                    \Magento\Framework\Oauth\Helper\Request::HTTP_BAD_REQUEST
-                )
+                array('msg', \Magento\Framework\Oauth\Helper\Request::HTTP_BAD_REQUEST)
             ),
             array(
                 new \Exception('msg'),
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Model/ManagerTest.php b/dev/tests/unit/testsuite/Magento/Integration/Model/ManagerTest.php
index 14613bd72d2..a90ca021e95 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Model/ManagerTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Model/ManagerTest.php
@@ -33,7 +33,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
     /**
      * Integration service
      *
-     * @var \Magento\Integration\Service\IntegrationV1Interface
+     * @var \Magento\Integration\Service\V1\IntegrationInterface
      */
     protected $_integrationServiceMock;
 
@@ -60,7 +60,7 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
         )->getMock();
 
         $this->_integrationServiceMock = $this->getMockBuilder(
-            '\Magento\Integration\Service\IntegrationV1'
+            '\Magento\Integration\Service\V1\Integration'
         )->disableOriginalConstructor()->setMethods(
             array('findByName', 'update', 'create')
         )->getMock();
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php b/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
index bad9bd6e67d..027c684f910 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Oauth/OauthTest.php
@@ -185,8 +185,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_VERSION_REJECTED
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 1
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
      */
     public function testGetRequestTokenVersionRejected()
     {
@@ -200,7 +199,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_CONSUMER_KEY_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 8
      */
     public function testGetRequestTokenConsumerKeyRejected()
     {
@@ -214,7 +212,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_CONSUMER_KEY_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 8
      */
     public function testGetRequestTokenConsumerKeyNotFound()
     {
@@ -233,7 +230,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_CONSUMER_KEY_INVALID
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 17
      */
     public function testGetRequestTokenOutdatedConsumerKey()
     {
@@ -300,8 +296,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_TIMESTAMP_REFUSED
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 4
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
      * @dataProvider dataProviderForGetRequestTokenNonceTimestampRefusedTest
      */
     public function testGetRequestTokenOauthTimestampRefused($timestamp)
@@ -352,7 +347,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_NONCE_USED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 5
      */
     public function testGetRequestTokenNonceAlreadyUsed()
     {
@@ -367,7 +361,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_CONSUMER_KEY_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 8
      */
     public function testGetRequestTokenNoConsumer()
     {
@@ -414,7 +407,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testGetRequestTokenTokenRejected()
     {
@@ -436,7 +428,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testGetRequestTokenTokenRejectedByType()
     {
@@ -458,8 +449,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_SIGNATURE_METHOD_REJECTED
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 6
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
      */
     public function testGetRequestTokenSignatureMethodRejected()
     {
@@ -478,7 +468,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_SIGNATURE_INVALID
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 7
      */
     public function testGetRequestTokenInvalidSignature()
     {
@@ -517,8 +506,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_VERSION_REJECTED
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 1
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
      */
     public function testGetAccessTokenVersionRejected()
     {
@@ -531,8 +519,8 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_PARAMETER_ABSENT
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 2
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
+     * @expectedExceptionMessage oauth_verifier is a required field.
      */
     public function testGetAccessTokenParameterAbsent()
     {
@@ -555,7 +543,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testGetAccessTokenTokenRejected()
     {
@@ -568,8 +555,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     /**
      * \Magento\Framework\Oauth\OauthInterface::ERR_SIGNATURE_METHOD_REJECTED
      *
-     * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 6
+     * @expectedException \Magento\Framework\Oauth\OauthInputException
      */
     public function testGetAccessTokenSignatureMethodRejected()
     {
@@ -583,7 +569,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_USED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 9
      */
     public function testGetAccessTokenTokenUsed()
     {
@@ -599,7 +584,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testGetAccessTokenConsumerIdDoesntMatch()
     {
@@ -614,7 +598,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_VERIFIER_INVALID
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 13
      * @dataProvider dataProviderForGetAccessTokenVerifierInvalidTest
      */
     public function testGetAccessTokenVerifierInvalid($verifier, $verifierFromToken)
@@ -657,7 +640,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testValidateAccessTokenRequestTokenRejected()
     {
@@ -672,7 +654,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testValidateAccessTokenRequestTokenRejectedByType()
     {
@@ -687,7 +668,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REVOKED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 11
      */
     public function testValidateAccessTokenRequestTokenRevoked()
     {
@@ -721,7 +701,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testValidateAccessTokenRejectedByType()
     {
@@ -735,7 +714,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REVOKED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 11
      */
     public function testValidateAccessTokenRevoked()
     {
@@ -755,7 +733,6 @@ class OauthTest extends \PHPUnit_Framework_TestCase
      * \Magento\Framework\Oauth\OauthInterface::ERR_TOKEN_REJECTED
      *
      * @expectedException \Magento\Framework\Oauth\Exception
-     * @expectedExceptionCode 12
      */
     public function testValidateAccessTokenNoConsumer()
     {
@@ -816,9 +793,9 @@ class OauthTest extends \PHPUnit_Framework_TestCase
     public function testMissingParamForBuildAuthorizationHeader($expectedMessage, $request)
     {
         $this->setExpectedException(
-            '\Magento\Framework\Oauth\Exception',
+            '\Magento\Framework\Oauth\OauthInputException',
             $expectedMessage,
-            \Magento\Framework\Oauth\OauthInterface::ERR_PARAMETER_ABSENT
+            0
         );
 
         $requestUrl = 'http://www.example.com/endpoint';
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/IntegrationV1Test.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/IntegrationTest.php
similarity index 98%
rename from dev/tests/unit/testsuite/Magento/Integration/Service/IntegrationV1Test.php
rename to dev/tests/unit/testsuite/Magento/Integration/Service/V1/IntegrationTest.php
index 45ce2165db6..6199dc10aa7 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/IntegrationV1Test.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/IntegrationTest.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Test for \Magento\Integration\Service\IntegrationV1
+ * Test for \Magento\Integration\Service\V1\Integration
  *
  * Magento
  *
@@ -23,11 +23,11 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
 use Magento\Integration\Model\Integration;
 
-class IntegrationV1Test extends \PHPUnit_Framework_TestCase
+class IntegrationTest extends \PHPUnit_Framework_TestCase
 {
     const VALUE_INTEGRATION_ID = 1;
 
@@ -52,7 +52,7 @@ class IntegrationV1Test extends \PHPUnit_Framework_TestCase
     /** @var \PHPUnit_Framework_MockObject_MockObject */
     private $_emptyIntegrationMock;
 
-    /** @var \Magento\Integration\Service\IntegrationV1 */
+    /** @var \Magento\Integration\Service\V1\Integration */
     private $_service;
 
     /** @var array */
@@ -98,7 +98,7 @@ class IntegrationV1Test extends \PHPUnit_Framework_TestCase
             'Magento\Authz\Model\UserIdentifier\Factory'
         )->disableOriginalConstructor()->getMock();
         $oauthConsumerHelper = $this->getMockBuilder(
-            'Magento\Integration\Service\OauthV1'
+            'Magento\Integration\Service\V1\Oauth'
         )->disableOriginalConstructor()->getMock();
         $oauthConsumer = $this->getMockBuilder(
             'Magento\Integration\Model\Oauth\Consumer'
@@ -116,7 +116,7 @@ class IntegrationV1Test extends \PHPUnit_Framework_TestCase
         )->disableOriginalConstructor()->getMock();
         $userIdentifierFactory->expects($this->any())->method('create')->will($this->returnValue($userIdentifier));
 
-        $this->_service = new \Magento\Integration\Service\IntegrationV1(
+        $this->_service = new \Magento\Integration\Service\V1\Integration(
             $this->_integrationFactory,
             $oauthConsumerHelper
         );
diff --git a/dev/tests/unit/testsuite/Magento/Integration/Service/OauthV1Test.php b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
similarity index 97%
rename from dev/tests/unit/testsuite/Magento/Integration/Service/OauthV1Test.php
rename to dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
index f9335092de0..2f6ca070d83 100644
--- a/dev/tests/unit/testsuite/Magento/Integration/Service/OauthV1Test.php
+++ b/dev/tests/unit/testsuite/Magento/Integration/Service/V1/OauthTest.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Test for \Magento\Integration\Service\OauthV1
+ * Test for \Magento\Integration\Service\V1\Oauth
  *
  * Magento
  *
@@ -23,13 +23,12 @@
  * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Integration\Service;
+namespace Magento\Integration\Service\V1;
 
 use Magento\Integration\Model\Integration;
-use Magento\Framework\Oauth\OauthInterface;
 use Magento\Integration\Model\Oauth\Token;
 
-class OauthV1Test extends \PHPUnit_Framework_TestCase
+class OauthTest extends \PHPUnit_Framework_TestCase
 {
     const VALUE_CONSUMER_ID = 1;
 
@@ -54,7 +53,7 @@ class OauthV1Test extends \PHPUnit_Framework_TestCase
      */
     private $_tokenMock;
 
-    /** @var \Magento\Integration\Service\OauthV1 */
+    /** @var \Magento\Integration\Service\V1\Oauth */
     private $_service;
 
     /** @var array */
@@ -108,7 +107,7 @@ class OauthV1Test extends \PHPUnit_Framework_TestCase
             $this->returnValue($this->_consumerMock)
         );
 
-        $this->_service = new \Magento\Integration\Service\OauthV1(
+        $this->_service = new \Magento\Integration\Service\V1\Oauth(
             $this->getMock('Magento\Store\Model\StoreManagerInterface', array(), array(), '', false),
             $this->_consumerFactory,
             $this->_tokenFactoryMock,
@@ -244,8 +243,7 @@ class OauthV1Test extends \PHPUnit_Framework_TestCase
         )->will(
             $this->throwException(
                 new \Magento\Framework\Oauth\Exception(
-                    'A token with consumer ID 0 does not exist',
-                    OauthInterface::ERR_TOKEN_REJECTED
+                    'A token with consumer ID 0 does not exist'
                 )
             )
         );
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Block/Bml/ShortcutTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Block/Bml/ShortcutTest.php
new file mode 100644
index 00000000000..c8f5672250b
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Block/Bml/ShortcutTest.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Block\Bml;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Catalog\Block as CatalogBlock;
+
+class ShortcutTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Paypal\Block\Bml\Shortcut */
+    protected $shortcut;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Payment\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $paymentHelperMock;
+
+    /** @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject */
+    protected $randomMock;
+
+    /** @var \Magento\Paypal\Helper\Shortcut\ValidatorInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $paypalShortcutHelperMock;
+
+    protected function setUp()
+    {
+        $this->paymentHelperMock = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
+        $this->randomMock = $this->getMock('Magento\Framework\Math\Random');
+        $this->paypalShortcutHelperMock = $this->getMock('Magento\Paypal\Helper\Shortcut\ValidatorInterface');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->shortcut = $this->objectManagerHelper->getObject(
+            'Magento\Paypal\Block\Bml\Shortcut',
+            [
+                'paymentData' => $this->paymentHelperMock,
+                'mathRandom' => $this->randomMock,
+                'shortcutValidator' => $this->paypalShortcutHelperMock,
+            ]
+        );
+    }
+
+    public function testIsOrPositionBefore()
+    {
+        $this->assertFalse($this->shortcut->isOrPositionBefore());
+        $this->shortcut->setShowOrPosition(CatalogBlock\ShortcutButtons::POSITION_BEFORE);
+        $this->assertTrue($this->shortcut->isOrPositionBefore());
+    }
+
+    public function testIsOrPositionAfter()
+    {
+        $this->assertFalse($this->shortcut->isOrPositionAfter());
+        $this->shortcut->setShowOrPosition(CatalogBlock\ShortcutButtons::POSITION_AFTER);
+        $this->assertTrue($this->shortcut->isOrPositionAfter());
+    }
+
+    public function testGetAlias()
+    {
+        $this->assertEmpty($this->shortcut->getAlias());
+    }
+
+    public function testToHtmlWrongValidation()
+    {
+        $isInCatalog = true;
+        $paymentMethodCode = '';
+        $this->shortcut->setIsInCatalogProduct($isInCatalog);
+
+        $this->paypalShortcutHelperMock->expects($this->once())->method('validate')
+            ->with($paymentMethodCode, $isInCatalog)->will($this->returnValue(false));
+
+        $this->assertEmpty($this->shortcut->toHtml());
+    }
+
+    public function testToHtmlMethodNotAvailable()
+    {
+        $isInCatalog = true;
+        $paymentMethodCode = '';
+        $bmlMethodCode = '';
+        $this->shortcut->setIsInCatalogProduct($isInCatalog);
+        $expressMethod = $this->getMockBuilder('Magento\Paypal\Model\Express')->disableOriginalConstructor()
+            ->setMethods([])->getMock();
+
+        $this->paypalShortcutHelperMock->expects($this->once())->method('validate')
+            ->with($paymentMethodCode, $isInCatalog)->will($this->returnValue(true));
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($bmlMethodCode)
+            ->will($this->returnValue($expressMethod));
+        $expressMethod->expects($this->once())->method('isAvailable')->will($this->returnValue(false));
+
+        $this->assertEmpty($this->shortcut->toHtml());
+    }
+
+    public function testToHtmlMethodSetBmlData()
+    {
+        $isInCatalog = true;
+        $paymentMethodCode = '';
+        $bmlMethodCode = '';
+        $hash = 'hash';
+        $this->shortcut->setIsInCatalogProduct($isInCatalog);
+        $expressMethod = $this->getMockBuilder('Magento\Paypal\Model\Express')->disableOriginalConstructor()
+            ->setMethods([])->getMock();
+        $expectedData = [
+            'is_in_catalog_product' => $isInCatalog,
+            'shortcut_html_id' => $hash,
+            'checkout_url' => null,
+            'image_url' => 'https://www.paypalobjects.com/webstatic/en_US/btn/btn_bml_SM.png',
+            'additional_link_image' => [
+                'href' => 'https://www.securecheckout.billmelater.com/paycapture-content/'
+                        .'fetch?hash=AU826TU8&content=/bmlweb/ppwpsiw.html',
+                'src' => 'https://www.paypalobjects.com/webstatic/en_US/btn/btn_bml_text.png'
+            ]
+        ];
+
+        $this->paypalShortcutHelperMock->expects($this->once())->method('validate')
+            ->with($paymentMethodCode, $isInCatalog)->will($this->returnValue(true));
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($bmlMethodCode)
+            ->will($this->returnValue($expressMethod));
+        $expressMethod->expects($this->once())->method('isAvailable')->will($this->returnValue(true));
+        $this->randomMock->expects($this->once())->method('getUniqueHash')->with('ec_shortcut_bml_')
+            ->will($this->returnValue($hash));
+
+        $this->assertEmpty($this->shortcut->toHtml());
+        $this->assertContains($expectedData, $this->shortcut->getData());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ReviewTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ReviewTest.php
index 4c532ea562f..5acc8e9b533 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ReviewTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ReviewTest.php
@@ -44,12 +44,40 @@ class ReviewTest extends \PHPUnit_Framework_TestCase
     protected function setUp()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+
+        $layout = $this->getMock('Magento\Framework\View\LayoutInterface', [], [], '', false);
+        $eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false);
+        $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
+
+        $scopeConfig->expects($this->any())
+            ->method('getValue')
+            ->with(
+                $this->stringContains('advanced/modules_disable_output/'),
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+            )->will($this->returnValue(false));
+
+        $urlBuilder = $this->getMock('Magento\Framework\UrlInterface');
+        $urlBuilder->expects($this->any())->method('getUrl')->will($this->returnArgument(0));
+
+        $context = $this->getMock(
+            'Magento\Framework\View\Element\Template\Context',
+            ['getLayout', 'getEventManager', 'getScopeConfig', 'getRequest', 'getAssetRepository', 'getUrlBuilder'],
+            [],
+            '',
+            false
+        );
+
         $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
         $this->assetRepo = $this->getMock('Magento\Framework\View\Asset\Repository', [], [], '', false);
-        $this->model = $helper->getObject(
-            'Magento\Paypal\Block\Express\Review',
-            ['request' => $this->request, 'assetRepo' => $this->assetRepo]
-        );
+
+        $context->expects($this->any())->method('getLayout')->will($this->returnValue($layout));
+        $context->expects($this->any())->method('getEventManager')->will($this->returnValue($eventManager));
+        $context->expects($this->any())->method('getScopeConfig')->will($this->returnValue($scopeConfig));
+        $context->expects($this->any())->method('getRequest')->will($this->returnValue($this->request));
+        $context->expects($this->any())->method('getAssetRepository')->will($this->returnValue($this->assetRepo));
+        $context->expects($this->any())->method('getUrlBuilder')->will($this->returnValue($urlBuilder));
+
+        $this->model = $helper->getObject('Magento\Paypal\Block\Express\Review', ['context' => $context]);
     }
 
     /**
@@ -72,4 +100,79 @@ class ReviewTest extends \PHPUnit_Framework_TestCase
     {
         return [[true], [false]];
     }
+
+    public function testBeforeToHtmlWhenQuoteIsNotVirtual()
+    {
+        $quote = $this->_getQuoteMock();
+        $quote->expects($this->any())->method('getIsVirtual')->will($this->returnValue(false));
+        $quote->setMayEditShippingMethod('MayEditShippingMethod');
+
+        $shippingRate = new \Magento\Framework\Object(['code' => 'Rate 1']);
+        $shippingRates = [
+            [$shippingRate]
+        ];
+        $quote->getShippingAddress()
+            ->expects($this->any())
+            ->method('getGroupedAllShippingRates')
+            ->will($this->returnValue($shippingRates));
+        $quote->getShippingAddress()
+            ->expects($this->any())
+            ->method('getShippingMethod')
+            ->will($this->returnValue($shippingRate->getCode()));
+
+        $this->model->setQuote($quote);
+        $this->model->toHtml();
+
+        $this->assertEquals(
+            $this->model->getPaymentMethodTitle(),
+            $quote->getPayment()->getMethodInstance()->getTitle()
+        );
+        $this->assertTrue($this->model->getShippingRateRequired());
+        $this->assertSame($shippingRates, $this->model->getShippingRateGroups());
+        $this->assertSame($shippingRate, $this->model->getCurrentShippingRate());
+        $this->assertNotNull($this->model->getCanEditShippingAddress());
+        $this->assertEquals($quote->getMayEditShippingMethod(), $this->model->getCanEditShippingMethod());
+        $this->assertContains('paypal/express/saveShippingMethod', $this->model->getShippingMethodSubmitUrl());
+        $this->assertContains('paypal/express/edit', $this->model->getEditUrl());
+        $this->assertContains('paypal/express/placeOrder', $this->model->getPlaceOrderUrl());
+    }
+
+    public function testBeforeToHtmlWhenQuoteIsVirtual()
+    {
+        $quote = $this->_getQuoteMock();
+        $quote->expects($this->any())->method('getIsVirtual')->will($this->returnValue(true));
+        $this->model->setQuote($quote);
+        $this->model->toHtml();
+        $this->assertEquals(
+            $this->model->getPaymentMethodTitle(),
+            $quote->getPayment()->getMethodInstance()->getTitle()
+        );
+        $this->assertFalse($this->model->getShippingRateRequired());
+        $this->assertContains('paypal/express/edit', $this->model->getEditUrl());
+        $this->assertContains('paypal/express/placeOrder', $this->model->getPlaceOrderUrl());
+    }
+
+    /**
+     * Create mock of sales quote model
+     *
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function _getQuoteMock()
+    {
+        $methodInstance = new \Magento\Framework\Object(['title' => 'Payment Method']);
+        $payment = $this->getMock('Magento\Sales\Model\Quote\Payment', [], [], '', false);
+        $payment->expects($this->any())->method('getMethodInstance')->will($this->returnValue($methodInstance));
+
+        $quote = $this->getMock('Magento\Sales\Model\Quote', [], [], '', false);
+        $quote->expects($this->any())->method('getPayment')->will($this->returnValue($payment));
+        $quote->setPayment($payment);
+
+        $address = $this->getMockBuilder('Magento\Sales\Model\Quote\Address')
+            ->disableOriginalConstructor()
+            ->setMethods(['getShippingMethod', 'getGroupedAllShippingRates', '__wakeup'])
+            ->getMock();
+        $quote->expects($this->any())->method('getShippingAddress')->will($this->returnValue($address));
+
+        return $quote;
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ShortcutTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ShortcutTest.php
index 2c73f77a257..b4878f399b4 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ShortcutTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Block/Express/ShortcutTest.php
@@ -26,18 +26,14 @@ namespace Magento\Paypal\Block\Express;
 class ShortcutTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Paypal\Block\Express\Shortcut|PHPUnit_Framework_MockObject_MockObject
+     * Alias
      */
-    protected $model;
-
-    protected function setUp()
-    {
-        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->model = $helper->getObject('Magento\Paypal\Block\Express\Shortcut');
-    }
+    const ALIAS = 'alias';
 
     public function testGetAlias()
     {
-        $this->assertEquals('product.info.addtocart.paypal', $this->model->getAlias());
+        $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $model = $helper->getObject('Magento\Paypal\Block\Express\Shortcut', ['alias' => self::ALIAS]);
+        $this->assertEquals(self::ALIAS, $model->getAlias());
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Controller/ExpressTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Controller/ExpressTest.php
new file mode 100644
index 00000000000..5e9b3fee891
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Controller/ExpressTest.php
@@ -0,0 +1,355 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Controller;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ExpressTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Express */
+    protected $model;
+
+    /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerSession;
+
+    /** @var \Magento\Checkout\Model\Session|\PHPUnit_Framework_MockObject_MockObject */
+    protected $checkoutSession;
+
+    /** @var \Magento\Paypal\Model\Express\Checkout\Factory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $checkoutFactory;
+
+    /** @var \Magento\Framework\Session\Generic|\PHPUnit_Framework_MockObject_MockObject */
+    protected $session;
+
+    /** @var \Magento\Sales\Model\Quote|\PHPUnit_Framework_MockObject_MockObject */
+    protected $quote;
+
+    /** @var \Magento\Customer\Service\V1\Data\Customer|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerData;
+
+    /** @var \Magento\Paypal\Model\Express\Checkout|\PHPUnit_Framework_MockObject_MockObject */
+    protected $checkout;
+
+    /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $request;
+
+    /** @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $redirect;
+
+    /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $response;
+
+    /** @var \Magento\Paypal\Model\Config|\PHPUnit_Framework_MockObject_MockObject */
+    protected $config;
+
+    /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $messageManager;
+
+    /** @var \Closure */
+    protected $objectManagerCallback;
+
+    protected function setUp()
+    {
+        $this->messageManager = $this->getMockForAbstractClass('Magento\Framework\Message\ManagerInterface');
+        $this->config = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
+        $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false);
+        $this->quote = $this->getMock('Magento\Sales\Model\Quote', [], [], '', false);
+        $this->quote->expects($this->any())
+            ->method('hasItems')
+            ->will($this->returnValue(true));
+        $this->redirect = $this->getMockForAbstractClass('Magento\Framework\App\Response\RedirectInterface');
+        $this->response = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false);
+        $this->customerData = $this->getMock('Magento\Customer\Service\V1\Data\Customer', [], [], '', false);
+        $this->checkout = $this->getMock('Magento\Paypal\Model\Express\Checkout', [], [], '', false);
+        $this->customerSession = $this->getMock('Magento\Customer\Model\Session', [], [], '', false);
+        $this->customerSession->expects($this->any())
+            ->method('getCustomerDataObject')
+            ->will($this->returnValue($this->customerData));
+        $this->checkoutSession = $this->getMock('Magento\Checkout\Model\Session', [], [], '', false);
+        $this->checkoutFactory = $this->getMock('Magento\Paypal\Model\Express\Checkout\Factory', [], [], '', false);
+        $this->checkoutFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->checkout));
+        $this->checkoutSession->expects($this->any())
+            ->method('getQuote')
+            ->will($this->returnValue($this->quote));
+        $this->session = $this->getMock('Magento\Framework\Session\Generic', [], [], '', false);
+        $objectManager = $this->getMock('Magento\Framework\ObjectManager', [], [], '', false);
+        $this->objectManagerCallback = function ($className) {
+            if ($className == 'Magento\Paypal\Model\Config') {
+                return $this->config;
+            }
+            return $this->getMock($className, [], [], '', false);
+        };
+        $objectManager->expects($this->any())
+            ->method('get')
+            ->will($this->returnCallback(function ($className) {
+                return call_user_func($this->objectManagerCallback, $className);
+            }));
+        $objectManager->expects($this->any())
+            ->method('create')
+            ->will($this->returnCallback(function ($className) {
+                return call_user_func($this->objectManagerCallback, $className);
+            }));
+
+        $helper = new ObjectManagerHelper($this);
+        $this->model = $helper->getObject(
+            'Magento\Paypal\Controller\Express',
+            [
+                'messageManager' => $this->messageManager,
+                'response' => $this->response,
+                'redirect' => $this->redirect,
+                'request' => $this->request,
+                'customerSession' => $this->customerSession,
+                'checkoutSession' => $this->checkoutSession,
+                'checkoutFactory' => $this->checkoutFactory,
+                'paypalSession' => $this->session,
+                'objectManager' => $objectManager,
+            ]
+        );
+    }
+
+    /**
+     * @param null|bool $buttonParam
+     * @dataProvider startActionDataProvider
+     */
+    public function testStartAction($buttonParam)
+    {
+        $this->request->expects($this->at(1))
+            ->method('getParam')
+            ->with('bml')
+            ->will($this->returnValue($buttonParam));
+        $this->checkout->expects($this->once())
+            ->method('setIsBml')
+            ->with((bool)$buttonParam);
+
+        $this->request->expects($this->at(2))
+            ->method('getParam')
+            ->with(\Magento\Paypal\Model\Express\Checkout::PAYMENT_INFO_BUTTON)
+            ->will($this->returnValue($buttonParam));
+        $this->customerData->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(1));
+        $this->checkout->expects($this->once())
+            ->method('start')
+            ->with($this->anything(), $this->anything(), (bool)$buttonParam);
+        $this->model->startAction();
+    }
+
+    public function startActionDataProvider()
+    {
+        return [['1'], [null]];
+    }
+
+    public function testReturnActionAuthorizationRetrial()
+    {
+        $this->request->expects($this->once())
+            ->method('getParam')
+            ->with('retry_authorization')
+            ->will($this->returnValue('true'));
+        $this->checkoutSession->expects($this->once())
+            ->method('__call')
+            ->with('getPaypalTransactionData')
+            ->will($this->returnValue(['any array']));
+        $this->_expectForwardPlaceOrder();
+        $this->model->returnAction();
+    }
+
+    /**
+     * @param bool $canSkipOrderReviewStep
+     * @dataProvider trueFalseDataProvider
+     */
+    public function testReturnAction($canSkipOrderReviewStep)
+    {
+        $this->checkoutSession->expects($this->at(0))
+            ->method('__call')
+            ->with('unsPaypalTransactionData');
+        $this->checkout->expects($this->once())
+            ->method('canSkipOrderReviewStep')
+            ->will($this->returnValue($canSkipOrderReviewStep));
+        if ($canSkipOrderReviewStep) {
+            $this->_expectForwardPlaceOrder();
+        } else {
+            $this->_expectRedirect();
+        }
+        $this->model->returnAction();
+    }
+
+    public function trueFalseDataProvider()
+    {
+        return [[true], [false]];
+    }
+
+    /**
+     * @param bool $isGeneral
+     * @dataProvider trueFalseDataProvider
+     */
+    public function testPlaceOrderActionNonProcessableException($isGeneral)
+    {
+        if (!$isGeneral) {
+            $this->request->expects($this->once())
+                ->method('getPost')
+                ->with('agreement', [])
+                ->will($this->returnValue([]));
+        }
+        $this->_expectRedirect();
+        $this->model->placeOrderAction();
+    }
+
+    /**
+     * @param int $code
+     * @param null|string $paymentAction
+     * @dataProvider placeOrderActionProcessableExceptionDataProvider
+     */
+    public function testPlaceOrderActionProcessableException($code, $paymentAction = null)
+    {
+        $this->request->expects($this->once())
+            ->method('getPost')
+            ->with('agreement', [])
+            ->will($this->returnValue([]));
+        $oldCallback = &$this->objectManagerCallback;
+        $this->objectManagerCallback = function ($className) use ($code, $oldCallback) {
+            $instance = call_user_func($oldCallback, $className);
+            if ($className == 'Magento\Checkout\Model\Agreements\AgreementsValidator') {
+                $exception = $this->getMock(
+                    'Magento\Paypal\Model\Api\ProcessableException',
+                    ['getUserMessage'],
+                    ['message', $code]
+                );
+                $exception->expects($this->any())
+                    ->method('getUserMessage')
+                    ->will($this->returnValue('User Message'));
+                $instance->expects($this->once())
+                    ->method('isValid')
+                    ->will($this->throwException($exception));
+            }
+            return $instance;
+        };
+        if (isset($paymentAction)) {
+            $this->config->expects($this->once())
+                ->method('getPaymentAction')
+                ->will($this->returnValue($paymentAction));
+        }
+        $this->_expectErrorCodes($code, $paymentAction);
+        $this->model->placeOrderAction();
+    }
+
+    public function placeOrderActionProcessableExceptionDataProvider()
+    {
+        return [
+            [\Magento\Paypal\Model\Api\ProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED],
+            [\Magento\Paypal\Model\Api\ProcessableException::API_TRANSACTION_EXPIRED],
+            [\Magento\Paypal\Model\Api\ProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL],
+            [
+                \Magento\Paypal\Model\Api\ProcessableException::API_UNABLE_TRANSACTION_COMPLETE,
+                \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER
+            ],
+            [\Magento\Paypal\Model\Api\ProcessableException::API_UNABLE_TRANSACTION_COMPLETE, 'other'],
+            [999999],
+        ];
+    }
+
+    private function _expectForwardPlaceOrder()
+    {
+        $this->request->expects($this->once())
+            ->method('setActionName')
+            ->with('placeOrder');
+        $this->request->expects($this->once())
+            ->method('setDispatched')
+            ->with(false);
+    }
+
+    /**
+     * @param string $path
+     */
+    private function _expectRedirect($path = '*/*/review')
+    {
+        $this->redirect->expects($this->once())
+            ->method('redirect')
+            ->with($this->anything(), $path, []);
+    }
+
+    /**
+     * @param int $code
+     * @param null|string $paymentAction
+     */
+    private function _expectErrorCodes($code, $paymentAction)
+    {
+        $redirectUrl = 'redirect by test';
+        if (in_array(
+            $code,
+            [
+                \Magento\Paypal\Model\Api\ProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED,
+                \Magento\Paypal\Model\Api\ProcessableException::API_TRANSACTION_EXPIRED,
+            ]
+        )
+        ) {
+            $payment = new \Magento\Framework\Object(['checkout_redirect_url' => $redirectUrl]);
+            $this->quote->expects($this->once())
+                ->method('getPayment')
+                ->will($this->returnValue($payment));
+        }
+        if ($code == \Magento\Paypal\Model\Api\ProcessableException::API_UNABLE_TRANSACTION_COMPLETE
+            && $paymentAction == \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER
+        ) {
+            $this->config->expects($this->once())
+                ->method('getExpressCheckoutOrderUrl')
+                ->will($this->returnValue($redirectUrl));
+        }
+        if ($code == \Magento\Paypal\Model\Api\ProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL
+            || $code == \Magento\Paypal\Model\Api\ProcessableException::API_UNABLE_TRANSACTION_COMPLETE
+            && $paymentAction != \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER
+        ) {
+            $this->config->expects($this->once())
+                ->method('getExpressCheckoutStartUrl')
+                ->will($this->returnValue($redirectUrl));
+            $this->request->expects($this->once())
+                ->method('getParam')
+                ->with('token');
+        }
+        if (in_array(
+            $code,
+            [
+                \Magento\Paypal\Model\Api\ProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED,
+                \Magento\Paypal\Model\Api\ProcessableException::API_TRANSACTION_EXPIRED,
+                \Magento\Paypal\Model\Api\ProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL,
+                \Magento\Paypal\Model\Api\ProcessableException::API_UNABLE_TRANSACTION_COMPLETE,
+            ]
+        )
+        ) {
+            $this->response->expects($this->once())
+                ->method('setRedirect')
+                ->with($redirectUrl);
+        } else {
+            $this->messageManager->expects($this->once())
+                ->method('addError')
+                ->with('User Message');
+            $this->_expectRedirect('checkout/cart');
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/CheckoutValidatorTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/CheckoutValidatorTest.php
new file mode 100644
index 00000000000..630fcb611b4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/CheckoutValidatorTest.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class CheckoutValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Paypal\Helper\Shortcut\CheckoutValidator */
+    protected $checkoutValidator;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Checkout\Model\Session|\PHPUnit_Framework_MockObject_MockObject */
+    protected $sessionMock;
+
+    /** @var \Magento\Paypal\Helper\Shortcut\Validator|\PHPUnit_Framework_MockObject_MockObject */
+    protected $paypalShortcutHelperMock;
+
+    /** @var \Magento\Payment\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
+    protected $paymentHelperMock;
+
+    protected function setUp()
+    {
+        $this->sessionMock = $this->getMock('Magento\Checkout\Model\Session', [], [], '', false);
+        $this->paypalShortcutHelperMock = $this->getMock('Magento\Paypal\Helper\Shortcut\Validator', [], [], '', false);
+        $this->paymentHelperMock = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->checkoutValidator = $this->objectManagerHelper->getObject(
+            'Magento\Paypal\Helper\Shortcut\CheckoutValidator',
+            [
+                'checkoutSession' => $this->sessionMock,
+                'shortcutValidator' => $this->paypalShortcutHelperMock,
+                'paymentData' => $this->paymentHelperMock
+            ]
+        );
+    }
+
+    public function testValidate()
+    {
+        $code = 'code';
+        $isInCatalog = true;
+        $methodInstanceMock = $this->getMockBuilder('Magento\Payment\Model\Method\AbstractMethod')
+            ->disableOriginalConstructor()->setMethods([])->getMock();
+
+        $this->paypalShortcutHelperMock->expects($this->once())->method('isContextAvailable')
+            ->with($code, $isInCatalog)->will($this->returnValue(true));
+        $this->paypalShortcutHelperMock->expects($this->once())->method('isPriceOrSetAvailable')
+            ->with($isInCatalog)->will($this->returnValue(true));
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($code)
+            ->will($this->returnValue($methodInstanceMock));
+        $methodInstanceMock->expects($this->once())->method('isAvailable')->with(null)
+            ->will($this->returnValue(true));
+
+        $this->assertTrue($this->checkoutValidator->validate($code, $isInCatalog));
+    }
+
+    public function testIsMethodQuoteAvailableNoQuoteNoMethodFalse()
+    {
+        $isInCatalog = true;
+        $paymentCode = 'code';
+        $methodInstanceMock = null;
+
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($paymentCode)
+            ->will($this->returnValue($methodInstanceMock));
+        $this->assertFalse($this->checkoutValidator->isMethodQuoteAvailable($paymentCode, $isInCatalog));
+    }
+    public function testIsMethodQuoteAvailableNoQuoteMethodNotAvailableFalse()
+    {
+        $quote = null;
+        $isInCatalog = true;
+        $paymentCode = 'code';
+        $methodInstanceMock = $this->getMockBuilder('Magento\Payment\Model\Method\AbstractMethod')
+            ->disableOriginalConstructor()->setMethods([])->getMock();
+
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($paymentCode)
+            ->will($this->returnValue($methodInstanceMock));
+        $methodInstanceMock->expects($this->once())->method('isAvailable')->with($quote)
+            ->will($this->returnValue(false));
+
+        $this->assertFalse($this->checkoutValidator->isMethodQuoteAvailable($paymentCode, $isInCatalog));
+    }
+
+    /**
+     * @dataProvider methodAvailabilityDataProvider
+     * @param bool $availability
+     */
+    public function testIsMethodQuoteAvailableWithQuoteMethodNotAvailable($availability)
+    {
+        $quote = $this->getMockBuilder('Magento\Sales\Model\Quote')->disableOriginalConstructor()->setMethods([])
+            ->getMock();
+        $isInCatalog = false;
+        $paymentCode = 'code';
+        $methodInstanceMock = $this->getMockBuilder('Magento\Payment\Model\Method\AbstractMethod')
+            ->disableOriginalConstructor()->setMethods([])->getMock();
+
+        $this->sessionMock->expects($this->once())->method('getQuote')->will($this->returnValue($quote));
+        $this->paymentHelperMock->expects($this->once())->method('getMethodInstance')->with($paymentCode)
+            ->will($this->returnValue($methodInstanceMock));
+        $methodInstanceMock->expects($this->once())->method('isAvailable')->with($quote)
+            ->will($this->returnValue($availability));
+
+        $this->assertEquals(
+            $availability,
+            $this->checkoutValidator->isMethodQuoteAvailable($paymentCode, $isInCatalog)
+        );
+    }
+
+    /**
+     * @return array
+     */
+    public function methodAvailabilityDataProvider()
+    {
+        return [[true], [false]];
+    }
+
+    public function testIsQuoteSummaryValidNoQuote()
+    {
+        $isInCatalog = true;
+        $this->assertTrue($this->checkoutValidator->isQuoteSummaryValid($isInCatalog));
+    }
+
+    public function testIsQuoteSummaryValidMinimumAmountFalse()
+    {
+        $isInCatalog = false;
+        $quote = $this->getMockBuilder('Magento\Sales\Model\Quote')->disableOriginalConstructor()->setMethods([])
+            ->getMock();
+
+        $this->sessionMock->expects($this->once())->method('getQuote')->will($this->returnValue($quote));
+        $quote->expects($this->once())->method('validateMinimumAmount')->will($this->returnValue(false));
+
+        $this->assertFalse($this->checkoutValidator->isQuoteSummaryValid($isInCatalog));
+    }
+
+    public function testIsQuoteSummaryValidGrandTotalFalse()
+    {
+        $isInCatalog = false;
+        $quote = $this->getMockBuilder('Magento\Sales\Model\Quote')->disableOriginalConstructor()
+            ->setMethods(['getGrandTotal', 'validateMinimumAmount', 'hasNominalItems', '__wakeup'])
+            ->getMock();
+
+        $this->sessionMock->expects($this->once())->method('getQuote')->will($this->returnValue($quote));
+        $quote->expects($this->once())->method('validateMinimumAmount')->will($this->returnValue(true));
+        $quote->expects($this->once())->method('getGrandTotal')->will($this->returnValue(0));
+        $quote->expects($this->once())->method('hasNominalItems')->will($this->returnValue(false));
+
+        $this->assertFalse($this->checkoutValidator->isQuoteSummaryValid($isInCatalog));
+    }
+
+    public function testIsQuoteSummaryValidTrue()
+    {
+        $isInCatalog = false;
+        $quote = $this->getMockBuilder('Magento\Sales\Model\Quote')->disableOriginalConstructor()
+            ->setMethods(['getGrandTotal', 'validateMinimumAmount', 'hasNominalItems', '__wakeup'])
+            ->getMock();
+
+        $this->sessionMock->expects($this->once())->method('getQuote')->will($this->returnValue($quote));
+        $quote->expects($this->once())->method('validateMinimumAmount')->will($this->returnValue(true));
+        $quote->expects($this->once())->method('getGrandTotal')->will($this->returnValue(1));
+
+        $this->assertTrue($this->checkoutValidator->isQuoteSummaryValid($isInCatalog));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/FactoryTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/FactoryTest.php
new file mode 100644
index 00000000000..a857d20472e
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/FactoryTest.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class FactoryTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \Magento\Paypal\Helper\Shortcut\Factory */
+    protected $factory;
+
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Framework\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */
+    protected $objectManagerMock;
+
+    protected function setUp()
+    {
+        $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManager');
+
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->factory = $this->objectManagerHelper->getObject(
+            'Magento\Paypal\Helper\Shortcut\Factory',
+            [
+                'objectManager' => $this->objectManagerMock
+            ]
+        );
+    }
+
+    public function testCreateDefault()
+    {
+        $instance = $this->getMockBuilder('Magento\Paypal\Helper\Shortcut\ValidatorInterface')->getMock();
+
+        $this->objectManagerMock->expects($this->once())->method('create')->with(Factory::DEFAULT_VALIDATOR)
+            ->will($this->returnValue($instance));
+
+        $this->assertInstanceOf(
+            'Magento\Paypal\Helper\Shortcut\ValidatorInterface',
+            $this->factory->create()
+        );
+    }
+
+    public function testCreateCheckout()
+    {
+        $checkoutMock = $this->getMockBuilder('Magento\Checkout\Model\Session')->disableOriginalConstructor()
+            ->setMethods([])->getMock();
+        $instance = $this->getMockBuilder('Magento\Paypal\Helper\Shortcut\ValidatorInterface')->getMock();
+
+        $this->objectManagerMock->expects($this->once())->method('create')->with(Factory::CHECKOUT_VALIDATOR)
+            ->will($this->returnValue($instance));
+
+        $this->assertInstanceOf(
+            'Magento\Paypal\Helper\Shortcut\ValidatorInterface',
+            $this->factory->create($checkoutMock)
+        );
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
new file mode 100644
index 00000000000..867c79fe172
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Helper/Shortcut/ValidatorTest.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Helper\Shortcut;
+
+class ValidatorTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $_paypalConfigFactory;
+
+    /** @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $_registry;
+
+    /** @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $_productTypeConfig;
+
+    /** @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $_paymentData;
+
+    /** @var \Magento\Paypal\Helper\Shortcut\Validator */
+    protected $helper;
+
+    protected function setUp()
+    {
+        $this->_paypalConfigFactory = $this->getMock('\Magento\Paypal\Model\ConfigFactory', ['create'], [], '', false);
+        $this->_productTypeConfig = $this->getMock(
+            'Magento\Catalog\Model\ProductTypes\ConfigInterface',
+            [],
+            [],
+            '',
+            false
+        );
+        $this->_registry = $this->getMock('Magento\Framework\Registry', [], [], '', false);
+        $this->_paymentData = $this->getMock('Magento\Payment\Helper\Data', [], [], '', false);
+
+        $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+        $this->helper = $objectManager->getObject(
+            'Magento\Paypal\Helper\Shortcut\Validator',
+            array(
+                'paypalConfigFactory' => $this->_paypalConfigFactory,
+                'registry' => $this->_registry,
+                'productTypeConfig' => $this->_productTypeConfig,
+                'paymentData' => $this->_paymentData
+            )
+        );
+    }
+
+    /**
+     * @dataProvider testIsContextAvailableDataProvider
+     * @param bool $isVisible
+     * @param bool $expected
+     */
+    public function testIsContextAvailable($isVisible, $expected)
+    {
+        $paypalConfig = $this->getMock('PaypalConfig', ['setMethod', 'getConfigValue']);
+        $paypalConfig->expects($this->any())
+            ->method('getConfigValue')
+            ->with($this->stringContains('visible_on'))
+            ->will($this->returnValue($isVisible));
+
+        $this->_paypalConfigFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($paypalConfig));
+
+        $this->assertEquals($expected, $this->helper->isContextAvailable('payment_code', true));
+    }
+
+    /**
+     * @return array
+     */
+    public function testIsContextAvailableDataProvider()
+    {
+        return [
+            [false, false],
+            [true, true]
+        ];
+    }
+
+    /**
+     * @dataProvider testIsPriceOrSetAvailableDataProvider
+     * @param bool $isInCatalog
+     * @param double $productPrice
+     * @param bool $isProductSet
+     * @param bool $expected
+     */
+    public function testIsPriceOrSetAvailable($isInCatalog, $productPrice, $isProductSet, $expected)
+    {
+        $currentProduct = new \Magento\Framework\Object(['final_price' => $productPrice, 'type_id' => 'simple']);
+        $this->_registry->expects($this->any())
+            ->method('registry')
+            ->with($this->equalTo('current_product'))
+            ->will($this->returnValue($currentProduct));
+
+        $this->_productTypeConfig->expects($this->any())
+            ->method('isProductSet')
+            ->will($this->returnValue($isProductSet));
+
+        $this->assertEquals($expected, $this->helper->isPriceOrSetAvailable($isInCatalog));
+    }
+
+    /**
+     * @return array
+     */
+    public function testIsPriceOrSetAvailableDataProvider()
+    {
+        return [
+            [false, 1, true, true],
+            [false, null, null, true],
+            [true, 0, false, false],
+            [true, 10, false, true],
+            [true, 0, true, true]
+        ];
+    }
+
+    /**
+     * @dataProvider testIsMethodAvailableDataProvider
+     * @param bool $methodExists
+     * @param bool $methodIsAvailable
+     * @param bool $expected
+     */
+    public function testIsMethodAvailable($methodExists, $methodIsAvailable, $expected)
+    {
+        $methodInstance = $this->getMock('MethodInstance', ['isAvailable']);
+        $methodInstance->expects($this->any())
+            ->method('isAvailable')
+            ->will($this->returnValue($methodIsAvailable));
+
+        $this->_paymentData->expects($this->any())
+            ->method('getMethodInstance')
+            ->will(
+                $this->returnValue($methodExists ? $methodInstance : false)
+            );
+
+        $this->assertEquals($expected, $this->helper->isMethodAvailable('payment_code'));
+    }
+
+    /**
+     * @return array
+     */
+    public function testIsMethodAvailableDataProvider()
+    {
+        return [
+            [false, true, false],
+            [true, false, false],
+            [false, false, false],
+            [true, true, true]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
new file mode 100644
index 00000000000..4bcee55b0f4
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/NvpTest.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model\Api;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class NvpTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var Nvp */
+    protected $model;
+
+    /** @var \Magento\Customer\Helper\Address|\PHPUnit_Framework_MockObject_MockObject */
+    protected $customerAddressHelper;
+
+    /** @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject */
+    protected $logger;
+
+    /** @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
+    protected $resolver;
+
+    /** @var \Magento\Directory\Model\RegionFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $regionFactory;
+
+    /** @var \PHPUnit_Framework_MockObject_MockObject */
+    protected $adapterFactory;
+
+    /** @var \Magento\Directory\Model\CountryFactory|\PHPUnit_Framework_MockObject_MockObject */
+    protected $countryFactory;
+
+    /** @var \Magento\Paypal\Model\Api\ProcessableException|\PHPUnit_Framework_MockObject_MockObject */
+    protected $processableException;
+
+    /** @var \Magento\Framework\Model\Exception|\PHPUnit_Framework_MockObject_MockObject */
+    protected $exception;
+
+    /** @var \Magento\Framework\HTTP\Adapter\Curl|\PHPUnit_Framework_MockObject_MockObject */
+    protected $curl;
+
+    /** @var \Magento\Paypal\Model\Config|\PHPUnit_Framework_MockObject_MockObject */
+    protected $config;
+
+    protected function setUp()
+    {
+        $this->customerAddressHelper = $this->getMock('Magento\Customer\Helper\Address', [], [], '', false);
+        $this->logger = $this->getMock('Magento\Framework\Logger', [], [], '', false);
+        $this->resolver = $this->getMock('Magento\Framework\Locale\ResolverInterface');
+        $this->regionFactory = $this->getMock('Magento\Directory\Model\RegionFactory', [], [], '', false);
+        $this->adapterFactory = $this->getMock('Magento\Framework\Logger\AdapterFactory');
+        $this->countryFactory = $this->getMock('Magento\Directory\Model\CountryFactory', [], [], '', false);
+        $processableExceptionFactory = $this->getMock(
+            'Magento\Paypal\Model\Api\ProcessableExceptionFactory',
+            ['create']
+        );
+        $processableExceptionFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnCallback(function ($arguments) {
+                $this->processableException = $this->getMock(
+                    'Magento\Paypal\Model\Api\ProcessableException',
+                    null,
+                    [$arguments['message'], $arguments['code']]
+                );
+                return $this->processableException;
+            }));
+        $exceptionFactory = $this->getMock('Magento\Framework\Model\ExceptionFactory', ['create']);
+        $exceptionFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnCallback(function ($arguments) {
+                $this->exception = $this->getMock(
+                    'Magento\Paypal\Model\Api\ProcessableException',
+                    null,
+                    [$arguments['message'], $arguments['code']]
+                );
+                return $this->exception;
+            }));
+        $this->curl = $this->getMock('Magento\Framework\HTTP\Adapter\Curl', [], [], '', false);
+        $curlFactory = $this->getMock('Magento\Framework\HTTP\Adapter\CurlFactory', ['create']);
+        $curlFactory->expects($this->any())->method('create')->will($this->returnValue($this->curl));
+        $this->config = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
+
+        $helper = new ObjectManagerHelper($this);
+        $this->model = $helper->getObject(
+            'Magento\Paypal\Model\Api\Nvp',
+            [
+                'customerAddress' => $this->customerAddressHelper,
+                'logger' => $this->logger,
+                'localeResolver' => $this->resolver,
+                'regionFactory' => $this->regionFactory,
+                'logAdapterFactory' => $this->adapterFactory,
+                'countryFactory' => $this->countryFactory,
+                'processableExceptionFactory' => $processableExceptionFactory,
+                'frameworkExceptionFactory' => $exceptionFactory,
+                'curlFactory' => $curlFactory,
+            ]
+        );
+        $this->model->setConfigObject($this->config);
+    }
+
+    /**
+     * @param string $response
+     * @param array $processableErrors
+     * @param null|string $exception
+     * @param string $exceptionMessage
+     * @param null|int $exceptionCode
+     * @dataProvider callDataProvider
+     */
+    public function testCall($response, $processableErrors, $exception, $exceptionMessage = '', $exceptionCode = null)
+    {
+        if (isset($exception)) {
+            $this->setExpectedException($exception, $exceptionMessage, $exceptionCode);
+        }
+        $this->curl->expects($this->once())
+            ->method('read')
+            ->will($this->returnValue($response));
+        $this->model->setProcessableErrors($processableErrors);
+        $this->model->call('some method', ['data' => 'some data']);
+    }
+
+    public function callDataProvider()
+    {
+        return [
+            ['', [], null],
+            [
+                "\r\n" . 'ACK=Failure&L_ERRORCODE0=10417&L_SHORTMESSAGE0=Message.&L_LONGMESSAGE0=Long%20Message.',
+                [],
+                'Magento\Framework\Model\Exception',
+                'PayPal gateway has rejected request. Long Message (#10417: Message).',
+                0
+            ],
+            [
+                "\r\n" . 'ACK=Failure&L_ERRORCODE0=10417&L_SHORTMESSAGE0=Message.&L_LONGMESSAGE0=Long%20Message.',
+                [10417, 10422],
+                'Magento\Paypal\Model\Api\ProcessableException',
+                'PayPal gateway has rejected request. Long Message (#10417: Message).',
+                10417
+            ],
+        ];
+    }
+
+    public function testCallGetExpressCheckoutDetails()
+    {
+        $this->curl->expects($this->once())
+            ->method('read')
+            ->will($this->returnValue(
+                "\r\n" . 'ACK=Success&SHIPTONAME=Ship%20To%20Name'
+            ));
+        $this->model->callGetExpressCheckoutDetails();
+        $this->assertEquals('Ship To Name', $this->model->getExportedShippingAddress()->getData('firstname'));
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/ProcessableExceptionTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/ProcessableExceptionTest.php
new file mode 100644
index 00000000000..df42091a67c
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/Api/ProcessableExceptionTest.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Paypal\Model\Api;
+
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
+class ProcessableExceptionTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var ObjectManagerHelper */
+    protected $objectManagerHelper;
+
+    /** @var \Magento\Paypal\Model\Api\ProcessableException */
+    protected $model;
+
+    /**
+     * @dataProvider getUserMessageDataProvider
+     */
+    public function testGetUserMessage($code, $msg)
+    {
+        $this->objectManagerHelper = new ObjectManagerHelper($this);
+        $this->model = $this->objectManagerHelper->getObject(
+            'Magento\Paypal\Model\Api\ProcessableException',
+            ['message' => $msg, 'code' => $code]
+        );
+        $this->assertEquals($msg, $this->model->getUserMessage());
+    }
+
+    /**
+     * @return array
+     */
+    public function getUserMessageDataProvider()
+    {
+        return [
+            [
+                10001,
+                "I'm sorry - but we were not able to process your payment. "
+                . "Please try another payment method or contact us so we can assist you."
+            ],
+            [
+                10417,
+                "I'm sorry - but we were not able to process your payment. "
+                . "Please try another payment method or contact us so we can assist you."
+            ],
+            [
+                10537,
+                "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
+            ],
+            [
+                10538,
+                "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
+            ],
+            [
+                10539,
+                "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
+            ],
+            [10411, "something went wrong"]
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/ConfigTest.php
index e64f6667d71..d75e1dbc74a 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/ConfigTest.php
@@ -23,6 +23,8 @@
  */
 namespace Magento\Paypal\Model;
 
+use Magento\Paypal\Model\Config as Config;
+
 class ConfigTest extends \PHPUnit_Framework_TestCase
 {
     /**
@@ -30,10 +32,31 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
      */
     protected $_model;
 
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_scopeConfig;
+
+    /**
+     * @var \Magento\Core\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_coreData;
+
     protected function setUp()
     {
         $helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = $helper->getObject('Magento\Paypal\Model\Config');
+        $this->_scopeConfig = $this->getMock(
+            'Magento\Framework\App\Config\ScopeConfigInterface',
+            ['getValue', 'isSetFlag'],
+            [],
+            '',
+            false
+        );
+        $this->_coreData = $this->getMock('Magento\Core\Helper\Data', ['getDefaultCountry'], [], '', false);
+        $this->_model = $helper->getObject(
+            'Magento\Paypal\Model\Config',
+            ['scopeConfig' => $this->_scopeConfig, 'coreData' => $this->_coreData]
+        );
     }
 
     public function testGetCountryMethods()
@@ -49,7 +72,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetBuildNotationCode()
     {
         $this->_model->setMethod('payflow_direct');
-        $this->assertEquals('Magento_Cart_WPP_some-country', $this->_model->getBuildNotationCode('some-country'));
+        $this->_model->setStoreId(123);
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('paypal/bncode', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, 123)
+            ->will($this->returnValue('some BN code'));
+        $this->assertEquals('some BN code', $this->_model->getBuildNotationCode());
     }
 
     public function testIsMethodActive()
@@ -57,11 +85,45 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($this->_model->isMethodActive('payflow_direct'));
     }
 
-    public function testIsMethodAvailable()
+    /**
+     * test for eliminating payflow_direct
+     */
+    public function testIsMethodAvailableWPPPE()
     {
         $this->assertFalse($this->_model->isMethodAvailable('payflow_direct'));
     }
 
+    /**
+     * @dataProvider isMethodAvailableDataProvider
+     */
+    public function testIsMethodAvailableForIsMethodActive($methodName, $expected)
+    {
+        $this->_scopeConfig->expects($this->any())
+            ->method('getValue')
+            ->with('paypal/general/merchant_country')
+            ->will($this->returnValue('US'));
+        $this->_scopeConfig->expects($this->exactly(2))
+            ->method('isSetFlag')
+            ->withAnyParameters()
+            ->will($this->returnValue(true));
+
+        $this->_model->setMethod($methodName);
+        $this->assertEquals($expected, $this->_model->isMethodAvailable($methodName));
+    }
+
+    /**
+     * @return array
+     */
+    public function isMethodAvailableDataProvider()
+    {
+        return [
+            [Config::METHOD_WPP_EXPRESS, true],
+            [Config::METHOD_WPP_BML, true],
+            [Config::METHOD_WPP_PE_EXPRESS, true],
+            [Config::METHOD_WPP_PE_BML, true],
+        ];
+    }
+
     public function testIsCreditCardMethod()
     {
         $this->assertFalse($this->_model->getIsCreditCardMethod('payflow_direct'));
@@ -72,5 +134,144 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         $this->_model->setMethod('payflow_direct');
         $this->assertNull($this->_model->getConfigValue('useccv'));
         $this->assertNull($this->_model->getConfigValue('vendor'));
+
+        // _mapBmlFieldset
+        $this->_model->setMethod(Config::METHOD_WPP_BML);
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/' . Config::METHOD_WPP_EXPRESS . '/allow_ba_signup')
+            ->will($this->returnValue(1));
+        $this->assertEquals(1, $this->_model->getConfigValue('allow_ba_signup'));
+    }
+
+    public function testGetSpecificConfigPathPayflow()
+    {
+        // _mapBmlPayflowFieldset
+        $this->_model->setMethod(Config::METHOD_WPP_PE_BML);
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/' . Config::METHOD_WPP_PE_EXPRESS . '/allow_ba_signup')
+            ->will($this->returnValue(1));
+        $this->assertEquals(1, $this->_model->getConfigValue('allow_ba_signup'));
+    }
+
+    /**
+     * @dataProvider skipOrderReviewStepDataProvider
+     */
+    public function testGetPayPalBasicStartUrl($value, $url)
+    {
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/paypal_express/skip_order_review_step')
+            ->will($this->returnValue($value));
+        $this->assertEquals($url, $this->_model->getPayPalBasicStartUrl('token'));
+    }
+
+    /**
+     * @return array
+     */
+    public function skipOrderReviewStepDataProvider()
+    {
+        return [
+            [true, 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=token&useraction=commit'],
+            [false, 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=token']
+        ];
+    }
+
+    public function testGetExpressCheckoutOrderUrl()
+    {
+        $url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&order_id=orderId';
+        $this->assertEquals($url, $this->_model->getExpressCheckoutOrderUrl('orderId'));
+    }
+
+    public function testGetBmlPublisherId()
+    {
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/' . Config::METHOD_WPP_BML . '/publisher_id')
+            ->will($this->returnValue('12345'));
+        $this->assertEquals('12345', $this->_model->getBmlPublisherId());
+    }
+
+    /**
+     * @dataProvider getBmlPositionDataProvider
+     */
+    public function testGetBmlPosition($section, $expected)
+    {
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/' . Config::METHOD_WPP_BML . '/' . $section . '_position')
+            ->will($this->returnValue($expected));
+        $this->assertEquals($expected, $this->_model->getBmlPosition($section));
+    }
+
+    /**
+     * @return array
+     */
+    public function getBmlPositionDataProvider()
+    {
+        return [
+            ['head', 'left'],
+            ['checkout', 'top']
+        ];
+    }
+
+    /**
+     * @dataProvider getBmlSizeDataProvider
+     */
+    public function testGetBmlSize($section, $expected)
+    {
+        $this->_scopeConfig->expects($this->once())
+            ->method('getValue')
+            ->with('payment/' . Config::METHOD_WPP_BML . '/' . $section . '_size')
+            ->will($this->returnValue($expected));
+        $this->assertEquals($expected, $this->_model->getBmlSize($section));
+    }
+
+    /**
+     * @return array
+     */
+    public function getBmlSizeDataProvider()
+    {
+        return [
+            ['head', '125x75'],
+            ['checkout', ['50x50']]
+        ];
+    }
+
+    /**
+     * @dataProvider dataProviderGetBmlDisplay
+     */
+    public function testGetBmlDisplay($section, $expectedValue, $expectedFlag, $expected)
+    {
+        $this->_model->setStoreId(1);
+        $this->_coreData->expects($this->any())
+            ->method('getDefaultCountry')
+            ->with(1)
+            ->will($this->returnValue('US'));
+        $this->_scopeConfig->expects($this->any())
+            ->method('isSetFlag')
+            ->will($this->returnValue($expectedFlag));
+        $this->_scopeConfig->expects($this->any())
+            ->method('getValue')
+            ->will($this->returnValueMap([
+                ['payment/' . Config::METHOD_WPP_BML . '/' . $section . '_display', 'store', 1, $expectedValue],
+                ['payment/' . Config::METHOD_WPP_BML . '/active', 'store', 1, $expectedValue],
+                ['payment/' . Config::METHOD_WPP_PE_BML . '/active', 'store', 1, $expectedValue],
+            ]));
+        $this->assertEquals($expected, $this->_model->getBmlDisplay($section));
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderGetBmlDisplay()
+    {
+        return [
+            ['head', true, true, true],
+            ['head', true, false, false],
+            ['head', false, true, false],
+            ['head', false, false, false],
+        ];
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/ExpressTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/ExpressTest.php
new file mode 100644
index 00000000000..ed54eceb1c3
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/ExpressTest.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Paypal\Model;
+
+use Magento\Framework\Object;
+use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException;
+
+class ExpressTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var array
+     */
+    protected $errorCodes = [
+        ApiProcessableException::API_INTERNAL_ERROR,
+        ApiProcessableException::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE,
+        ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL,
+        ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE,
+        ApiProcessableException::API_TRANSACTION_EXPIRED,
+        ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED,
+        ApiProcessableException::API_COUNTRY_FILTER_DECLINE,
+        ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
+        ApiProcessableException::API_OTHER_FILTER_DECLINE
+    ];
+
+    /**
+     * @var Express
+     */
+    protected $_model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_checkoutSession;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_pro;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_nvp;
+
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $_helper;
+
+    protected function setUp()
+    {
+        $this->_checkoutSession = $this->getMock(
+            'Magento\Checkout\Model\Session',
+            ['getPaypalTransactionData', 'setPaypalTransactionData'],
+            [],
+            '',
+            false
+        );
+        $this->_nvp = $this->getMock(
+            'Magento\Paypal\Model\Api\Nvp',
+            ['setProcessableErrors', 'setAmount', 'setCurrencyCode', 'setTransactionId', 'callDoAuthorization'],
+            [],
+            '',
+            false
+        );
+        $this->_pro = $this->getMock(
+            'Magento\Paypal\Model\ProFactory',
+            ['create', 'setMethod', 'getApi', 'importPaymentInfo', 'resetApi'],
+            [],
+            '',
+            false
+        );
+        $this->_pro->expects($this->any())->method('create')->will($this->returnSelf());
+        $this->_helper = new \Magento\TestFramework\Helper\ObjectManager($this);
+    }
+
+    public function testSetApiProcessableErrors()
+    {
+        $this->_nvp->expects($this->once())->method('setProcessableErrors')->with($this->errorCodes);
+        $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp));
+        $this->_model = $this->_helper->getObject(
+            'Magento\Paypal\Model\Express',
+            ['proFactory' => $this->_pro, 'checkoutSession' => $this->_checkoutSession]
+        );
+    }
+
+    public function testOrder()
+    {
+        $this->_nvp->expects($this->any())->method('setProcessableErrors')->will($this->returnSelf());
+        $this->_nvp->expects($this->any())->method('setAmount')->will($this->returnSelf());
+        $this->_nvp->expects($this->any())->method('setCurrencyCode')->will($this->returnSelf());
+        $this->_nvp->expects($this->any())->method('setTransactionId')->will($this->returnSelf());
+        $this->_nvp->expects($this->any())->method('callDoAuthorization')->will($this->returnSelf());
+        $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp));
+        $this->_checkoutSession->expects($this->once())->method('getPaypalTransactionData')->will(
+            $this->returnValue([])
+        );
+        $this->_checkoutSession->expects($this->once())->method('setPaypalTransactionData')->with([]);
+
+        $currency = $this->getMock('Magento\Directory\Model\Currency', ['__wakeup', 'formatTxt'], [], '', false);
+        $paymentModel = $this->getMock(
+            'Magento\Sales\Model\Order\Payment',
+            ['__wakeup', 'getBaseCurrency', 'getOrder', 'getIsTransactionPending', 'addStatusHistoryComment'],
+            [],
+            '',
+            false
+        );
+        $paymentModel->expects($this->any())->method('getOrder')->will($this->returnSelf());
+        $paymentModel->expects($this->any())->method('getBaseCurrency')->will($this->returnValue($currency));
+        $paymentModel->expects($this->any())->method('getIsTransactionPending')->will($this->returnSelf());
+        $this->_model = $this->_helper->getObject(
+            'Magento\Paypal\Model\Express',
+            ['proFactory' => $this->_pro, 'checkoutSession' => $this->_checkoutSession]
+        );
+        $this->_model->order($paymentModel, 12.3);
+        $this->assertEquals('payment_review', $paymentModel->getState());
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/ObserverTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/ObserverTest.php
index e23897d75ec..af13ef68e42 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/ObserverTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/ObserverTest.php
@@ -92,23 +92,23 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
         )->setMethods(
             array('createBlock')
         )->disableOriginalConstructor()->getMock();
-        $blocks = array('Magento\Paypal\Block\Express\Shortcut', 'Magento\Paypal\Block\PayflowExpress\Shortcut');
+        $blocks = [
+            'Magento\Paypal\Block\Express\Shortcut' => 'Magento\Paypal\Block\Express\Shortcut',
+            'Magento\Paypal\Block\PayflowExpress\Shortcut' => 'Magento\Paypal\Block\Express\Shortcut',
+            'Magento\Paypal\Block\Bml\Shortcut' => 'Magento\Paypal\Block\Bml\Shortcut',
+            'Magento\Paypal\Block\Payflow\Bml\Shortcut' => 'Magento\Paypal\Block\Bml\Shortcut'
+        ];
 
         $blockInstances = array();
-        foreach ($blocks as $atPosition => $blockName) {
-            $block = $this->getMockBuilder($blockName)->setMethods(null)->disableOriginalConstructor()->getMock();
+        $atPosition = 0;
+        foreach ($blocks as $blockName => $blockInstance) {
+            $block = $this->getMockBuilder($blockInstance)->setMethods(null)->disableOriginalConstructor()->getMock();
 
             $blockInstances[$blockName] = $block;
 
-            $layoutMock->expects(
-                new MethodInvokedAtIndex($atPosition)
-            )->method(
-                'createBlock'
-            )->with(
-                $blockName
-            )->will(
-                $this->returnValue($block)
-            );
+            $layoutMock->expects(new MethodInvokedAtIndex($atPosition))->method('createBlock')->with($blockName)
+                ->will($this->returnValue($block));
+            $atPosition++;
         }
 
         $shortcutButtonsMock = $this->getMockBuilder(
@@ -119,18 +119,18 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
 
         $shortcutButtonsMock->expects($this->any())->method('getLayout')->will($this->returnValue($layoutMock));
 
-        foreach ($blocks as $atPosition => $blockName) {
-            $shortcutButtonsMock->expects(
-                new MethodInvokedAtIndex($atPosition)
-            )->method(
-                'addShortcut'
-            )->with(
-                $this->identicalTo($blockInstances[$blockName])
-            );
+        $atPosition = 0;
+        foreach (array_keys($blocks) as $blockName) {
+            $shortcutButtonsMock->expects(new MethodInvokedAtIndex($atPosition))->method('addShortcut')
+                ->with($this->identicalTo($blockInstances[$blockName]));
+            $atPosition++;
         }
-
         $this->_event->setContainer($shortcutButtonsMock);
         $this->_model->addPaypalShortcuts($this->_observer);
+
+        foreach ($blockInstances as $instance) {
+            $this->assertEquals(\Magento\Paypal\Model\Observer::SHORTCUT_TEMPLATE, $instance->getTemplate());
+        }
     }
 
     /**
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowExpressTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowExpressTest.php
index 9ddcf127db8..fad235f1737 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowExpressTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowExpressTest.php
@@ -44,9 +44,11 @@ class PayflowExpressTest extends \PHPUnit_Framework_TestCase
         $proFactory = $this->getMockBuilder(
             'Magento\Paypal\Model\ProFactory'
         )->disableOriginalConstructor()->setMethods(['create'])->getMock();
+        $api = $this->getMock('Magento\Paypal\Model\Api\Nvp', [], [], '', false);
         $paypalPro = $this->getMockBuilder(
             'Magento\Paypal\Model\Pro'
         )->disableOriginalConstructor()->setMethods([])->getMock();
+        $paypalPro->expects($this->any())->method('getApi')->will($this->returnValue($api));
 
         $proFactory->expects($this->once())->method('create')->will($this->returnValue($paypalPro));
 
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowadvancedTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowadvancedTest.php
deleted file mode 100644
index 67db4c96a29..00000000000
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowadvancedTest.php
+++ /dev/null
@@ -1,326 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-
-/**
- * Test class for \Magento\Paypal\Model\Payflowadvanced
- *
- */
-namespace Magento\Paypal\Model;
-
-class PayflowadvancedTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var
-     */
-    protected $_modelClass;
-
-    /**
-     * Paypal sent request
-     *
-     * @var \Magento\Framework\Object
-     */
-    public static $request;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $_moduleList;
-
-    /**#@+
-     *
-     * Test response parameters
-     */
-    const PARAMETER_FIRSTNAME = 'Firstname';
-
-    const PARAMETER_LASTNAME = 'Lastname';
-
-    const PARAMETER_ADDRESS = '111 Streetname Street';
-
-    const PARAMETER_CITY = 'City';
-
-    const PARAMETER_STATE = 'State';
-
-    const PARAMETER_ZIP = '11111';
-
-    const PARAMETER_COUNTRY = 'Country';
-
-    const PARAMETER_PHONE = '111-11-11';
-
-    const PARAMETER_EMAIL = 'email@example.com';
-
-    const PARAMETER_NAMETOSHIP = 'Name to ship';
-
-    const PARAMETER_ADDRESSTOSHIP = '112 Streetname Street';
-
-    const PARAMETER_CITYTOSHIP = 'City to ship';
-
-    const PARAMETER_STATETOSHIP = 'State to ship';
-
-    const PARAMETER_ZIPTOSHIP = '22222';
-
-    const PARAMETER_COUNTRYTOSHIP = 'Country to ship';
-
-    const PARAMETER_PHONETOSHIP = '222-22-22';
-
-    const PARAMETER_EMAILTOSHIP = 'emailtoship@example.com';
-
-    const PARAMETER_FAXTOSHIP = '333-33-33';
-
-    const PARAMETER_METHOD = 'CC';
-
-    const PARAMETER_CSCMATCH = 'Y';
-
-    const PARAMETER_AVSADDR = 'X';
-
-    const PARAMETER_AVSZIP = 'N';
-
-    const PARAMETER_TYPE = 'A';
-
-    /**#@-*/
-    protected function setUp()
-    {
-        $order = $this->getMockBuilder('Magento\Sales\Model\Order')->disableOriginalConstructor()->getMock();
-        $payment = $this->getMockBuilder(
-            'Magento\Sales\Model\Order\Payment'
-        )->disableOriginalConstructor()->setMethods(
-            array('getOrder', '__wakeup')
-        )->getMock();
-        $payment->expects($this->any())->method('getOrder')->will($this->returnValue($order));
-        $request = new \Magento\Paypal\Model\Payflow\Request();
-        $this->_modelClass = $this->getMock(
-            'Magento\Paypal\Model\Payflowadvanced',
-            array(
-                'getResponse',
-                '_postRequest',
-                '_processTokenErrors',
-                'getInfoInstance',
-                '_generateSecureSilentPostHash',
-                '_buildTokenRequest',
-                '_getCallbackUrl'
-            ),
-            array(),
-            '',
-            false
-        );
-        $this->_modelClass->expects($this->any())->method('getResponse')->will($this->returnValue($request));
-        $this->_modelClass->expects($this->any())->method('getInfoInstance')->will($this->returnValue($payment));
-        $this->_modelClass->expects(
-            $this->any()
-        )->method(
-            '_generateSecureSilentPostHash'
-        )->will(
-            $this->returnValue(md5('1234567890'))
-        );
-        $this->_modelClass->expects($this->any())->method('_postRequest')->will($this->returnValue(true));
-        $this->_modelClass->expects($this->any())->method('_processTokenErrors')->will($this->returnValue(true));
-    }
-
-    public function testSetResponseData()
-    {
-        // Setting legacy parameters
-        /** @var $model \Magento\Paypal\Model\Payflowadvanced */
-        $model = $this->_modelClass;
-        $model->setResponseData(
-            array(
-                'NAME' => self::PARAMETER_FIRSTNAME . ' ' . self::PARAMETER_LASTNAME,
-                'FIRSTNAME' => self::PARAMETER_FIRSTNAME,
-                'LASTNAME' => self::PARAMETER_LASTNAME,
-                'ADDRESS' => self::PARAMETER_ADDRESS,
-                'CITY' => self::PARAMETER_CITY,
-                'STATE' => self::PARAMETER_STATE,
-                'ZIP' => self::PARAMETER_ZIP,
-                'COUNTRY' => self::PARAMETER_COUNTRY,
-                'PHONE' => self::PARAMETER_PHONE,
-                'EMAIL' => self::PARAMETER_EMAIL,
-                'NAMETOSHIP' => self::PARAMETER_NAMETOSHIP,
-                'ADDRESSTOSHIP' => self::PARAMETER_ADDRESSTOSHIP,
-                'CITYTOSHIP' => self::PARAMETER_CITYTOSHIP,
-                'STATETOSHIP' => self::PARAMETER_STATETOSHIP,
-                'ZIPTOSHIP' => self::PARAMETER_ZIPTOSHIP,
-                'COUNTRYTOSHIP' => self::PARAMETER_COUNTRYTOSHIP,
-                'PHONETOSHIP' => self::PARAMETER_PHONETOSHIP,
-                'EMAILTOSHIP' => self::PARAMETER_EMAILTOSHIP,
-                'FAXTOSHIP' => self::PARAMETER_FAXTOSHIP,
-                'METHOD' => self::PARAMETER_METHOD,
-                'CSCMATCH' => self::PARAMETER_CSCMATCH,
-                'AVSDATA' => self::PARAMETER_AVSADDR . self::PARAMETER_AVSZIP,
-                'TYPE' => self::PARAMETER_TYPE
-            )
-        );
-
-        $this->_assertResponseData($model);
-
-        // Setting new parameters
-        /** @var $model \Magento\Paypal\Model\Payflowadvanced */
-        $model = $this->_modelClass;
-        $model->setResponseData(
-            array(
-                'BILLTOFIRSTNAME' => self::PARAMETER_FIRSTNAME,
-                'BILLTOLASTNAME' => self::PARAMETER_LASTNAME,
-                'BILLTOSTREET' => self::PARAMETER_ADDRESS,
-                'BILLTOCITY' => self::PARAMETER_CITY,
-                'BILLTOSTATE' => self::PARAMETER_STATE,
-                'BILLTOZIP' => self::PARAMETER_ZIP,
-                'BILLTOCOUNTRY' => self::PARAMETER_COUNTRY,
-                'BILLTOPHONE' => self::PARAMETER_PHONE,
-                'BILLTOEMAIL' => self::PARAMETER_EMAIL,
-                'SHIPTOFIRSTNAME' => self::PARAMETER_NAMETOSHIP,
-                'SHIPTOSTREET' => self::PARAMETER_ADDRESSTOSHIP,
-                'SHIPTOCITY' => self::PARAMETER_CITYTOSHIP,
-                'SHIPTOSTATE' => self::PARAMETER_STATETOSHIP,
-                'SHIPTOZIP' => self::PARAMETER_ZIPTOSHIP,
-                'SHIPTOCOUNTRY' => self::PARAMETER_COUNTRYTOSHIP,
-                'SHIPTOPHONE' => self::PARAMETER_PHONETOSHIP,
-                'SHIPTOEMAIL' => self::PARAMETER_EMAILTOSHIP,
-                'SHIPTOFAX' => self::PARAMETER_FAXTOSHIP,
-                'TENDER' => self::PARAMETER_METHOD,
-                'CVV2MATCH' => self::PARAMETER_CSCMATCH,
-                'AVSADDR' => self::PARAMETER_AVSADDR,
-                'AVSZIP' => self::PARAMETER_AVSZIP,
-                'TRXTYPE' => self::PARAMETER_TYPE
-            )
-        );
-        $this->_assertResponseData($model);
-    }
-
-    /**
-     * @dataProvider defaultRequestParameters
-     */
-    public function testDefaultRequestParameters($cscrequired, $cscedit, $emailcustomer, $urlmethod)
-    {
-        $params = array($cscrequired, $cscedit, $emailcustomer, $urlmethod);
-        /** @var $model \Magento\Paypal\Model\Payflowadvanced */
-        $model = $this->_modelClass;
-        $this->_prepareRequest($model, $params);
-
-        // check whether all parameters were sent
-        $request = \Magento\Paypal\Model\PayflowadvancedTest::$request;
-        $this->_assertRequestBaseParameters($model);
-        $this->assertEquals($cscrequired, $request->getCscrequired());
-        $this->assertEquals($cscedit, $request->getCscedit());
-        $this->assertEquals($emailcustomer, $request->getEmailcustomer());
-        $this->assertEquals($urlmethod, $request->getUrlmethod());
-    }
-
-    /**
-     * Prepare request for test
-     *
-     * @param \Magento\Paypal\Model\Payflowadvanced $model
-     * @param array() $params
-     */
-    protected function _prepareRequest(\Magento\Paypal\Model\Payflowadvanced $model, $params)
-    {
-        $request = new \Magento\Paypal\Model\Payflow\Request();
-        $request->setCancelurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'cancelPayment'
-        )->setErrorurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'returnUrl'
-        )->setSilentpost(
-            'TRUE'
-        )->setSilentposturl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'silentPost'
-        )->setReturnurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'returnUrl'
-        )->setTemplate(
-            'minLayout'
-        )->setDisablereceipt(
-            'TRUE'
-        )->setCscrequired(
-            $params[0]
-        )->setCscedit(
-            $params[1]
-        )->setEmailcustomer(
-            $params[2]
-        )->setUrlmethod(
-            $params[3]
-        );
-        $model->expects($this->any())->method('_buildTokenRequest')->will($this->returnValue($request));
-
-        $checkRequest = create_function('$request', 'Magento\Paypal\Model\PayflowadvancedTest::$request = $request;');
-        $model->expects($this->any())->method('_postRequest')->will($this->returnCallback($checkRequest));
-        \Magento\Paypal\Model\PayflowlinkTest::$request = null;
-        $model->initialize(\Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH, new \Magento\Framework\Object());
-    }
-
-    /**
-     * Assert request not configurable parameters
-     *
-     * @param \Magento\Paypal\Model\Payflowadvanced $model
-     */
-    protected function _assertRequestBaseParameters(\Magento\Paypal\Model\Payflowadvanced $model)
-    {
-        $controllerPath = '/paypal/' . $model->getCallbackController() . '/';
-        $request = \Magento\Paypal\Model\PayflowadvancedTest::$request;
-        $this->assertEquals($controllerPath . 'cancelPayment', $request->getData('cancelurl'));
-        $this->assertEquals($controllerPath . 'returnUrl', $request->getData('errorurl'));
-        $this->assertEquals($controllerPath . 'silentPost', $request->getData('silentposturl'));
-        $this->assertEquals($controllerPath . 'returnUrl', $request->getData('returnurl'));
-        $this->assertEquals(\Magento\Paypal\Model\Payflowlink::LAYOUT_TEMPLATE, $request->getData('template'));
-        $this->assertEquals('TRUE', $request->getData('silentpost'));
-        $this->assertEquals('TRUE', $request->getData('disablereceipt'));
-    }
-
-    /**
-     * Assert response data
-     *
-     * @param \Magento\Paypal\Model\Payflowadvanced $model
-     */
-    protected function _assertResponseData(\Magento\Paypal\Model\Payflowadvanced $model)
-    {
-        $data = $model->getResponse()->getData();
-        $this->assertEquals(self::PARAMETER_FIRSTNAME . ' ' . self::PARAMETER_LASTNAME, $data['name']);
-        $this->assertEquals(self::PARAMETER_FIRSTNAME, $data['firstname']);
-        $this->assertEquals(self::PARAMETER_LASTNAME, $data['lastname']);
-        $this->assertEquals(self::PARAMETER_ADDRESS, $data['address']);
-        $this->assertEquals(self::PARAMETER_CITY, $data['city']);
-        $this->assertEquals(self::PARAMETER_STATE, $data['state']);
-        $this->assertEquals(self::PARAMETER_ZIP, $data['zip']);
-        $this->assertEquals(self::PARAMETER_COUNTRY, $data['country']);
-        $this->assertEquals(self::PARAMETER_PHONE, $data['phone']);
-        $this->assertEquals(self::PARAMETER_EMAIL, $data['email']);
-        $this->assertEquals(self::PARAMETER_NAMETOSHIP, $data['nametoship']);
-        $this->assertEquals(self::PARAMETER_ADDRESSTOSHIP, $data['addresstoship']);
-        $this->assertEquals(self::PARAMETER_CITYTOSHIP, $data['citytoship']);
-        $this->assertEquals(self::PARAMETER_STATETOSHIP, $data['statetoship']);
-        $this->assertEquals(self::PARAMETER_ZIPTOSHIP, $data['ziptoship']);
-        $this->assertEquals(self::PARAMETER_COUNTRYTOSHIP, $data['countrytoship']);
-        $this->assertEquals(self::PARAMETER_PHONETOSHIP, $data['phonetoship']);
-        $this->assertEquals(self::PARAMETER_EMAILTOSHIP, $data['emailtoship']);
-        $this->assertEquals(self::PARAMETER_FAXTOSHIP, $data['faxtoship']);
-        $this->assertEquals(self::PARAMETER_METHOD, $data['method']);
-        $this->assertEquals(self::PARAMETER_CSCMATCH, $data['cscmatch']);
-        $this->assertEquals(self::PARAMETER_AVSADDR . self::PARAMETER_AVSZIP, $data['avsdata']);
-        $this->assertEquals(self::PARAMETER_TYPE, $data['type']);
-    }
-
-    /**
-     * Data Provider for test defaultRequestParameters
-     *
-     * @return array
-     */
-    public function defaultRequestParameters()
-    {
-        return array(array('TRUE', 'TRUE', 'FALSE', 'GET'), array('FALSE', 'FALSE', 'TRUE', 'POST'));
-    }
-}
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
index 7f79a1e7bee..2d6e8d5c1f1 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowlinkTest.php
@@ -22,305 +22,85 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-/**
- * Test class for \Magento\Paypal\Model\Payflowlink
- *
- */
 namespace Magento\Paypal\Model;
 
+use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper;
+
 class PayflowlinkTest extends \PHPUnit_Framework_TestCase
 {
-    /**
-     * @var
-     */
-    protected $_modelClass;
-
-    /**
-     * Paypal sent request
-     *
-     * @var \Magento\Framework\Object
-     */
-    public static $request;
-
-    /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $_moduleListMock;
-
-    /**#@+
-     *
-     * Test response parameters
-     */
-    const PARAMETER_FIRSTNAME = 'Firstname';
-
-    const PARAMETER_LASTNAME = 'Lastname';
-
-    const PARAMETER_ADDRESS = '111 Streetname Street';
-
-    const PARAMETER_CITY = 'City';
-
-    const PARAMETER_STATE = 'State';
-
-    const PARAMETER_ZIP = '11111';
-
-    const PARAMETER_COUNTRY = 'Country';
-
-    const PARAMETER_PHONE = '111-11-11';
-
-    const PARAMETER_EMAIL = 'email@example.com';
-
-    const PARAMETER_NAMETOSHIP = 'Name to ship';
-
-    const PARAMETER_ADDRESSTOSHIP = '112 Streetname Street';
-
-    const PARAMETER_CITYTOSHIP = 'City to ship';
-
-    const PARAMETER_STATETOSHIP = 'State to ship';
-
-    const PARAMETER_ZIPTOSHIP = '22222';
-
-    const PARAMETER_COUNTRYTOSHIP = 'Country to ship';
-
-    const PARAMETER_PHONETOSHIP = '222-22-22';
-
-    const PARAMETER_EMAILTOSHIP = 'emailtoship@example.com';
-
-    const PARAMETER_FAXTOSHIP = '333-33-33';
+    /** @var Payflowlink */
+    protected $model;
 
-    const PARAMETER_METHOD = 'CC';
+    /** @var  \Magento\Sales\Model\Order\Payment|\PHPUnit_Framework_MockObject_MockObject */
+    protected $infoInstance;
 
-    const PARAMETER_CSCMATCH = 'Y';
+    /** @var  \Magento\Paypal\Model\Payflow\Request|\PHPUnit_Framework_MockObject_MockObject */
+    protected $payflowRequest;
 
-    const PARAMETER_AVSADDR = 'X';
+    /** @var  \Magento\Paypal\Model\Config|\PHPUnit_Framework_MockObject_MockObject */
+    protected $paypalConfig;
 
-    const PARAMETER_AVSZIP = 'N';
+    /** @var  \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject */
+    protected $store;
 
-    const PARAMETER_TYPE = 'A';
-
-    /**#@-*/
     protected function setUp()
     {
-        $order = $this->getMockBuilder('Magento\Sales\Model\Order')->disableOriginalConstructor()->getMock();
-        $payment = $this->getMockBuilder(
-            'Magento\Sales\Model\Order\Payment'
-        )->disableOriginalConstructor()->setMethods(
-            array('getOrder', '__wakeup')
-        )->getMock();
-        $payment->expects($this->any())->method('getOrder', '__wakeup')->will($this->returnValue($order));
-        $request = new \Magento\Paypal\Model\Payflow\Request();
-        $this->_modelClass = $this->getMock(
+        $this->store = $this->getMock('Magento\Store\Model\Store', [], [], '', false);
+        $storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface');
+        $storeManager->expects($this->any())
+            ->method('getStore')
+            ->will($this->returnValue($this->store));
+        $this->paypalConfig = $this->getMock('Magento\Paypal\Model\Config', [], [], '', false);
+        $configFactory = $this->getMock('Magento\Paypal\Model\ConfigFactory', ['create']);
+        $configFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->paypalConfig));
+        $this->payflowRequest = $this->getMock('Magento\Paypal\Model\Payflow\Request', [], [], '', false);
+        $this->payflowRequest->expects($this->any())
+            ->method('__call')
+            ->will($this->returnCallback(function ($method) {
+                if (strpos($method, 'set') === 0) {
+                    return $this->payflowRequest;
+                }
+                return null;
+            }));
+        $requestFactory = $this->getMock('Magento\Paypal\Model\Payflow\RequestFactory', ['create']);
+        $requestFactory->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->payflowRequest));
+        $this->infoInstance = $this->getMock('Magento\Sales\Model\Order\Payment', [], [], '', false);
+
+        $helper = new ObjectManagerHelper($this);
+        $this->model = $helper->getObject(
             'Magento\Paypal\Model\Payflowlink',
-            array(
-                'getResponse',
-                '_postRequest',
-                '_processTokenErrors',
-                'getInfoInstance',
-                '_generateSecureSilentPostHash',
-                '_buildTokenRequest',
-                '_getCallbackUrl'
-            ),
-            array(),
-            '',
-            false
-        );
-        $this->_modelClass->expects($this->any())->method('getResponse')->will($this->returnValue($request));
-        $this->_modelClass->expects($this->any())->method('getInfoInstance')->will($this->returnValue($payment));
-        $this->_modelClass->expects(
-            $this->any()
-        )->method(
-            '_generateSecureSilentPostHash'
-        )->will(
-            $this->returnValue(md5('1234567890'))
-        );
-        $this->_modelClass->expects($this->any())->method('_postRequest')->will($this->returnValue(true));
-        $this->_modelClass->expects($this->any())->method('_processTokenErrors')->will($this->returnValue(true));
-    }
-
-    public function testSetResponseData()
-    {
-        // Setting legacy parameters
-        /** @var $model \Magento\Paypal\Model\Payflowlink */
-        $model = $this->_modelClass;
-        $model->setResponseData(
-            array(
-                'NAME' => self::PARAMETER_FIRSTNAME . ' ' . self::PARAMETER_LASTNAME,
-                'FIRSTNAME' => self::PARAMETER_FIRSTNAME,
-                'LASTNAME' => self::PARAMETER_LASTNAME,
-                'ADDRESS' => self::PARAMETER_ADDRESS,
-                'CITY' => self::PARAMETER_CITY,
-                'STATE' => self::PARAMETER_STATE,
-                'ZIP' => self::PARAMETER_ZIP,
-                'COUNTRY' => self::PARAMETER_COUNTRY,
-                'PHONE' => self::PARAMETER_PHONE,
-                'EMAIL' => self::PARAMETER_EMAIL,
-                'NAMETOSHIP' => self::PARAMETER_NAMETOSHIP,
-                'ADDRESSTOSHIP' => self::PARAMETER_ADDRESSTOSHIP,
-                'CITYTOSHIP' => self::PARAMETER_CITYTOSHIP,
-                'STATETOSHIP' => self::PARAMETER_STATETOSHIP,
-                'ZIPTOSHIP' => self::PARAMETER_ZIPTOSHIP,
-                'COUNTRYTOSHIP' => self::PARAMETER_COUNTRYTOSHIP,
-                'PHONETOSHIP' => self::PARAMETER_PHONETOSHIP,
-                'EMAILTOSHIP' => self::PARAMETER_EMAILTOSHIP,
-                'FAXTOSHIP' => self::PARAMETER_FAXTOSHIP,
-                'METHOD' => self::PARAMETER_METHOD,
-                'CSCMATCH' => self::PARAMETER_CSCMATCH,
-                'AVSDATA' => self::PARAMETER_AVSADDR . self::PARAMETER_AVSZIP,
-                'TYPE' => self::PARAMETER_TYPE
-            )
-        );
-
-        $this->_assertResponseData($model);
-
-        // Setting new parameters
-        /** @var $model \Magento\Paypal\Model\Payflowlink */
-        $model = $this->_modelClass;
-        $model->setResponseData(
-            array(
-                'BILLTOFIRSTNAME' => self::PARAMETER_FIRSTNAME,
-                'BILLTOLASTNAME' => self::PARAMETER_LASTNAME,
-                'BILLTOSTREET' => self::PARAMETER_ADDRESS,
-                'BILLTOCITY' => self::PARAMETER_CITY,
-                'BILLTOSTATE' => self::PARAMETER_STATE,
-                'BILLTOZIP' => self::PARAMETER_ZIP,
-                'BILLTOCOUNTRY' => self::PARAMETER_COUNTRY,
-                'BILLTOPHONE' => self::PARAMETER_PHONE,
-                'BILLTOEMAIL' => self::PARAMETER_EMAIL,
-                'SHIPTOFIRSTNAME' => self::PARAMETER_NAMETOSHIP,
-                'SHIPTOSTREET' => self::PARAMETER_ADDRESSTOSHIP,
-                'SHIPTOCITY' => self::PARAMETER_CITYTOSHIP,
-                'SHIPTOSTATE' => self::PARAMETER_STATETOSHIP,
-                'SHIPTOZIP' => self::PARAMETER_ZIPTOSHIP,
-                'SHIPTOCOUNTRY' => self::PARAMETER_COUNTRYTOSHIP,
-                'SHIPTOPHONE' => self::PARAMETER_PHONETOSHIP,
-                'SHIPTOEMAIL' => self::PARAMETER_EMAILTOSHIP,
-                'SHIPTOFAX' => self::PARAMETER_FAXTOSHIP,
-                'TENDER' => self::PARAMETER_METHOD,
-                'CVV2MATCH' => self::PARAMETER_CSCMATCH,
-                'AVSADDR' => self::PARAMETER_AVSADDR,
-                'AVSZIP' => self::PARAMETER_AVSZIP,
-                'TRXTYPE' => self::PARAMETER_TYPE
-            )
+            [
+                'storeManager' => $storeManager,
+                'configFactory' => $configFactory,
+                'requestFactory' => $requestFactory,
+            ]
         );
-        $this->_assertResponseData($model);
-    }
-
-    /**
-     * @dataProvider defaultRequestParameters
-     */
-    public function testDefaultRequestParameters($cscrequired, $cscedit, $emailcustomer, $urlmethod)
-    {
-        $params = array($cscrequired, $cscedit, $emailcustomer, $urlmethod);
-        /** @var $model \Magento\Paypal\Model\Payflowlink */
-        $model = $this->_modelClass;
-        $this->_prepareRequest($model, $params);
-
-        // check whether all parameters were sent
-        $request = \Magento\Paypal\Model\PayflowlinkTest::$request;
-        $this->_assertRequestBaseParameters($model);
-        $this->assertEquals($cscrequired, $request->getCscrequired());
-        $this->assertEquals($cscedit, $request->getCscedit());
-        $this->assertEquals($emailcustomer, $request->getEmailcustomer());
-        $this->assertEquals($urlmethod, $request->getUrlmethod());
+        $this->model->setInfoInstance($this->infoInstance);
     }
 
     /**
-     * Prepare request for test
-     *
-     * @param \Magento\Paypal\Model\Payflowlink $model
-     * @param array() $params
+     * @expectedException \Magento\Framework\Model\Exception
      */
-    protected function _prepareRequest(\Magento\Paypal\Model\Payflowlink $model, $params)
+    public function testInitialize()
     {
-        $request = new \Magento\Paypal\Model\Payflow\Request();
-        $request->setCancelurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'cancelPayment'
-        )->setErrorurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'returnUrl'
-        )->setSilentpost(
-            'TRUE'
-        )->setSilentposturl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'silentPost'
-        )->setReturnurl(
-            '/paypal/' . $model->getCallbackController() . '/' . 'returnUrl'
-        )->setTemplate(
-            'minLayout'
-        )->setDisablereceipt(
-            'TRUE'
-        )->setCscrequired(
-            $params[0]
-        )->setCscedit(
-            $params[1]
-        )->setEmailcustomer(
-            $params[2]
-        )->setUrlmethod(
-            $params[3]
+        $order = $this->getMock('Magento\Sales\Model\Order', [], [], '', false);
+        $this->infoInstance->expects($this->any())
+            ->method('getOrder')
+            ->will($this->returnValue($order));
+        $this->paypalConfig->expects($this->once())
+            ->method('getBuildNotationCode')
+            ->will($this->returnValue('build notation code'));
+        $this->payflowRequest->expects($this->once())
+            ->method('setData')
+            ->with('BNCODE', 'build notation code')
+            ->will($this->returnSelf());
+        $this->model->initialize(
+            \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH,
+            new \Magento\Framework\Object()
         );
-        $model->expects($this->any())->method('_buildTokenRequest')->will($this->returnValue($request));
-
-        $checkRequest = create_function('$request', 'Magento\Paypal\Model\PayflowlinkTest::$request = $request;');
-        $model->expects($this->any())->method('_postRequest')->will($this->returnCallback($checkRequest));
-        \Magento\Paypal\Model\PayflowlinkTest::$request = null;
-        $model->initialize(\Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH, new \Magento\Framework\Object());
-    }
-
-    /**
-     * Assert request not configurable parameters
-     *
-     * @param \Magento\Paypal\Model\Payflowlink $model
-     */
-    protected function _assertRequestBaseParameters(\Magento\Paypal\Model\Payflowlink $model)
-    {
-        $controllerPath = '/paypal/' . $model->getCallbackController() . '/';
-        $request = \Magento\Paypal\Model\PayflowlinkTest::$request;
-        $this->assertEquals($controllerPath . 'cancelPayment', $request->getData('cancelurl'));
-        $this->assertEquals($controllerPath . 'returnUrl', $request->getData('errorurl'));
-        $this->assertEquals($controllerPath . 'silentPost', $request->getData('silentposturl'));
-        $this->assertEquals($controllerPath . 'returnUrl', $request->getData('returnurl'));
-        $this->assertEquals(\Magento\Paypal\Model\Payflowlink::LAYOUT_TEMPLATE, $request->getData('template'));
-        $this->assertEquals('TRUE', $request->getData('silentpost'));
-        $this->assertEquals('TRUE', $request->getData('disablereceipt'));
-    }
-
-    /**
-     * Assert response data
-     *
-     * @param \Magento\Paypal\Model\Payflowlink $model
-     */
-    protected function _assertResponseData(\Magento\Paypal\Model\Payflowlink $model)
-    {
-        $data = $model->getResponse()->getData();
-        $this->assertEquals(self::PARAMETER_FIRSTNAME . ' ' . self::PARAMETER_LASTNAME, $data['name']);
-        $this->assertEquals(self::PARAMETER_FIRSTNAME, $data['firstname']);
-        $this->assertEquals(self::PARAMETER_LASTNAME, $data['lastname']);
-        $this->assertEquals(self::PARAMETER_ADDRESS, $data['address']);
-        $this->assertEquals(self::PARAMETER_CITY, $data['city']);
-        $this->assertEquals(self::PARAMETER_STATE, $data['state']);
-        $this->assertEquals(self::PARAMETER_ZIP, $data['zip']);
-        $this->assertEquals(self::PARAMETER_COUNTRY, $data['country']);
-        $this->assertEquals(self::PARAMETER_PHONE, $data['phone']);
-        $this->assertEquals(self::PARAMETER_EMAIL, $data['email']);
-        $this->assertEquals(self::PARAMETER_NAMETOSHIP, $data['nametoship']);
-        $this->assertEquals(self::PARAMETER_ADDRESSTOSHIP, $data['addresstoship']);
-        $this->assertEquals(self::PARAMETER_CITYTOSHIP, $data['citytoship']);
-        $this->assertEquals(self::PARAMETER_STATETOSHIP, $data['statetoship']);
-        $this->assertEquals(self::PARAMETER_ZIPTOSHIP, $data['ziptoship']);
-        $this->assertEquals(self::PARAMETER_COUNTRYTOSHIP, $data['countrytoship']);
-        $this->assertEquals(self::PARAMETER_PHONETOSHIP, $data['phonetoship']);
-        $this->assertEquals(self::PARAMETER_EMAILTOSHIP, $data['emailtoship']);
-        $this->assertEquals(self::PARAMETER_FAXTOSHIP, $data['faxtoship']);
-        $this->assertEquals(self::PARAMETER_METHOD, $data['method']);
-        $this->assertEquals(self::PARAMETER_CSCMATCH, $data['cscmatch']);
-        $this->assertEquals(self::PARAMETER_AVSADDR . self::PARAMETER_AVSZIP, $data['avsdata']);
-        $this->assertEquals(self::PARAMETER_TYPE, $data['type']);
-    }
-
-    /**
-     * Data Provider for test defaultRequestParameters
-     *
-     * @return array
-     */
-    public function defaultRequestParameters()
-    {
-        return array(array('TRUE', 'TRUE', 'FALSE', 'GET'), array('FALSE', 'FALSE', 'TRUE', 'POST'));
     }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
index 8a2d1c4499d..50467279928 100644
--- a/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
+++ b/dev/tests/unit/testsuite/Magento/Paypal/Model/PayflowproTest.php
@@ -39,10 +39,25 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
      */
     protected $_helper;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $_configFactory;
+
     protected function setUp()
     {
+        $this->_configFactory = $this->getMock(
+            'Magento\Paypal\Model\ConfigFactory',
+            ['create', 'getBuildNotationCode'],
+            [],
+            '',
+            false
+        );
         $this->_helper = new \Magento\TestFramework\Helper\ObjectManager($this);
-        $this->_model = $this->_helper->getObject('Magento\Paypal\Model\Payflowpro');
+        $this->_model = $this->_helper->getObject(
+            'Magento\Paypal\Model\Payflowpro',
+            ['configFactory' => $this->_configFactory]
+        );
     }
 
     /**
@@ -58,6 +73,9 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expected, $this->_model->canVoid($payment));
     }
 
+    /**
+     * @return array
+     */
     public function canVoidDataProvider()
     {
         return array(
@@ -78,4 +96,19 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
     {
         $this->assertTrue($this->_model->canRefundPartialPerInvoice());
     }
+
+    /**
+     * test for _buildBasicRequest (BDCODE) and catch exception of response
+     */
+    public function testFetchTransactionInfoForBNException()
+    {
+        $this->_configFactory->expects($this->once())->method('create')->will($this->returnSelf());
+        $this->_configFactory->expects($this->once())->method('getBuildNotationCode')
+            ->will($this->returnValue('BNCODE'));
+        $payment = $this->getMock('Magento\Payment\Model\Info', [], [], '', false);
+        $this->setExpectedException(
+            'Magento\Framework\Model\Exception', 'User authentication failed'
+        );
+        $this->_model->fetchTransactionInfo($payment, 'AD49G8N825');
+    }
 }
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Order/HistoryTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Order/HistoryTest.php
index 30ec667e3f0..bd046e5dce2 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Block/Order/HistoryTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Order/HistoryTest.php
@@ -63,7 +63,7 @@ class HistoryTest extends \PHPUnit_Framework_TestCase
         );
         $this->customerSession = $this->getMock(
             'Magento\Customer\Model\Session',
-            ['getCustomer'],
+            ['getCustomerId'],
             [],
             '',
             false,
@@ -91,13 +91,9 @@ class HistoryTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(false));
 
         $customerId = 25;
-        $customer = $this->getMock('Magento\Customer\Model\Customer', ['__wakeUp', 'getId'], [], '', false, false);
-        $customer->expects($this->once())
-            ->method('getId')
-            ->will($this->returnValue($customerId));
         $this->customerSession->expects($this->once())
-            ->method('getCustomer')
-            ->will($this->returnValue($customer));
+            ->method('getCustomerId')
+            ->will($this->returnValue($customerId));
 
         $statuses = ['pending', 'processing', 'comlete'];
         $this->orderConfig->expects($this->once())
diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Order/RecentTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Order/RecentTest.php
index 8796aa2dd10..8c17eaf2f90 100644
--- a/dev/tests/unit/testsuite/Magento/Sales/Block/Order/RecentTest.php
+++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Order/RecentTest.php
@@ -63,7 +63,7 @@ class RecentTest extends \PHPUnit_Framework_TestCase
         );
         $this->customerSession = $this->getMock(
             'Magento\Customer\Model\Session',
-            ['getCustomer'],
+            ['getCustomerId'],
             [],
             '',
             false,
@@ -88,13 +88,9 @@ class RecentTest extends \PHPUnit_Framework_TestCase
         $this->context->expects($this->once())
             ->method('getLayout')
             ->will($this->returnValue($layout));
-        $customer = $this->getMock('Magento\Customer\Model\Customer', ['__wakeUp', 'getId'], [], '', false, false);
-        $customer->expects($this->once())
-            ->method('getId')
-            ->will($this->returnValue($customerId));
         $this->customerSession->expects($this->once())
-            ->method('getCustomer')
-            ->will($this->returnValue($customer));
+            ->method('getCustomerId')
+            ->will($this->returnValue($customerId));
 
         $statuses = ['pending', 'processing', 'complete'];
         $this->orderConfig->expects($this->once())
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
new file mode 100644
index 00000000000..f118a6687dd
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/Rate/ConverterTest.php
@@ -0,0 +1,254 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Model\Calculation\Rate;
+
+class ConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\TestFramework\Helper\ObjectManager
+     */
+    protected $objectManager;
+
+    public function setUp()
+    {
+        $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this);
+    }
+
+    /**
+     * @param array $valueMap
+     * @dataProvider createTaxRateDataObjectFromModelDataProvider
+     */
+    public function testCreateTaxRateDataObjectFromModel($valueMap)
+    {
+        $taxRateModelMock = $this->getMockBuilder(
+            'Magento\Tax\Model\Calculation\Rate'
+        )->disableOriginalConstructor()->setMethods(
+            [
+                'getId',
+                'getCountryId',
+                'getRegionId',
+                'getTaxPostcode',
+                'getCode',
+                'getRate',
+                'getZipIsRange',
+                'getZipFrom',
+                'getZipTo',
+                '__wakeup',
+            ]
+        )->getMock();
+        $this->mockReturnValue($taxRateModelMock, $valueMap);
+
+        $taxRateDataOjectBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $zipRangeDataObjectBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        /** @var  $converter \Magento\Tax\Model\Calculation\Rate\Converter */
+        $converter = $this->objectManager->getObject(
+            'Magento\Tax\Model\Calculation\Rate\Converter',
+            [
+                'taxRateDataObjectBuilder' => $taxRateDataOjectBuilder,
+                'zipRangeDataObjectBuilder' => $zipRangeDataObjectBuilder,
+            ]
+        );
+        $taxRateDataObject = $converter->createTaxRateDataObjectFromModel($taxRateModelMock);
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getId'), $taxRateDataObject->getId());
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getTaxCountryId'), $taxRateDataObject->getCountryId());
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getTaxRegionId'), $taxRateDataObject->getRegionId());
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getTaxPostcode'), $taxRateDataObject->getPostcode());
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getCode'), $taxRateDataObject->getcode());
+        $this->assertEquals($this->getExpectedValue($valueMap, 'getRate'), $taxRateDataObject->getPercentageRate());
+        $zipIsRange = $this->getExpectedValue($valueMap, 'getZipIsRange');
+        if ($zipIsRange) {
+            $this->assertEquals(
+                $this->getExpectedValue($valueMap, 'getZipFrom'),
+                $taxRateDataObject->getZipRange()->getFrom()
+            );
+            $this->assertEquals(
+                $this->getExpectedValue($valueMap, 'getZipTo'),
+                $taxRateDataObject->getZipRange()->getTo()
+            );
+        } else {
+            $this->assertNull($taxRateDataObject->getZipRange());
+        }
+    }
+
+    public function createTaxRateDataObjectFromModelDataProvider()
+    {
+        return [
+            [
+                [
+                    'getId' => '1',
+                    'getCountryId' => 'US',
+                    'getRegionId' => '34',
+                    'getCode' => 'US-CA-*-Rate 1',
+                    'getRate' => '8.25',
+                    'getZipIsRange' => '1',
+                    'getZipFrom' => '78701',
+                    'getZipTo' => '78759',
+                ],
+            ],
+            [
+                [
+                    'getId' => '1',
+                    'getCountryId' => 'US',
+                    'getCode' => 'US-CA-*-Rate 1',
+                    'getRate' => '8.25',
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @param array $data
+     * @dataProvider createTaxRateModelDataProvider
+     */
+    public function testCreateTaxRateModel($data)
+    {
+        $zipRangeBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        $taxRateBuilder = $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\Data\TaxRateBuilder',
+            ['zipRangeBuilder' => $zipRangeBuilder]
+        );
+        /** @var  $taxRateDataObject \Magento\Tax\Service\V1\Data\TaxRate */
+        $taxRateDataObject = $taxRateBuilder->populateWithArray($data)->create();
+
+        $rateModelMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rate')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'setId',
+                    'setTaxCountryId',
+                    'setTaxRegionId',
+                    'setTaxPostcode',
+                    'setRate',
+                    'setZipFrom',
+                    'setZipTo',
+                    '__wakeup',
+                ]
+            )
+            ->getMock();
+
+        $rateModelMock->expects($this->once())
+            ->method('setId')
+            ->with($taxRateDataObject->getId());
+        $rateModelMock->expects($this->once())
+            ->method('setTaxCountryId')
+            ->with($taxRateDataObject->getCountryId());
+        $rateModelMock->expects($this->once())
+            ->method('setTaxRegionId')
+            ->with($taxRateDataObject->getRegionId());
+        $rateModelMock->expects($this->once())
+            ->method('setTaxPostcode')
+            ->with($taxRateDataObject->getPostcode());
+        $rateModelMock->expects($this->once())
+            ->method('setRate')
+            ->with($taxRateDataObject->getPercentageRate());
+        if ($taxRateDataObject->getZipRange()) {
+            $rateModelMock->expects($this->once())
+                ->method('setZipFrom')
+                ->with($taxRateDataObject->getZipRange()->getFrom());
+            $rateModelMock->expects($this->once())
+                ->method('setZipTo')
+                ->with($taxRateDataObject->getZipRange()->getTo());
+        }
+
+        $rateModelFactoryMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\RateFactory')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rateModelFactoryMock->expects($this->once())->method('create')->will($this->returnValue($rateModelMock));
+
+        /** @var  $converter \Magento\Tax\Model\Calculation\Rate\Converter */
+        $converter = $this->objectManager->getObject(
+            'Magento\Tax\Model\Calculation\Rate\Converter',
+            [
+                'taxRateDataObjectBuilder' => $taxRateBuilder,
+                'taxRateModelFactory' => $rateModelFactoryMock,
+                'zipRangeDataObjectBuilder' => $zipRangeBuilder
+            ]
+        );
+
+        $taxRateModel = $converter->createTaxRateModel($taxRateDataObject);
+
+        $this->assertSame($rateModelMock, $taxRateModel);
+    }
+
+    public function createTaxRateModelDataProvider()
+    {
+        return [
+            'withZipRange' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['from' => 78765, 'to' => 78780]
+                ],
+            ],
+            'withZipRangeFrom' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['from' => 78765]
+                ],
+            ],
+            'withZipRangeTo' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'region_id' => '34',
+                    'code' => 'US-CA-*-Rate 2',
+                    'percentage_rate' => '8.25',
+                    'zip_range' => ['to' => 78780]
+                ],
+            ],
+            'withPostalCode' => [
+                [
+                    'id' => '1',
+                    'country_id' => 'US',
+                    'code' => 'US-CA-*-Rate 1',
+                    'rate' => '8.25',
+                    'postcode' => '78727'
+                ],
+            ]
+        ];
+    }
+
+    private function getExpectedValue($valueMap, $key)
+    {
+        return array_key_exists($key, $valueMap) ? $valueMap[$key] : null;
+    }
+
+    /**
+     * @param \PHPUnit_Framework_MockObject_MockObject $mock
+     * @param array $valueMap
+     */
+    private function mockReturnValue(\PHPUnit_Framework_MockObject_MockObject $mock, $valueMap)
+    {
+        foreach ($valueMap as $method => $value) {
+            $mock->expects($this->any())->method($method)->will($this->returnValue($value));
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RateRegistryTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RateRegistryTest.php
new file mode 100644
index 00000000000..ad5d4725496
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/RateRegistryTest.php
@@ -0,0 +1,150 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestFramework\Helper\ObjectManager;
+
+/**
+ * Test for RateRegistry
+ *
+ */
+class RateRegistryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Tax\Model\Calculation\RateRegistry
+     */
+    private $rateRegistry;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\RateFactory
+     */
+    private $rateModelFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\Rate
+     */
+    private $rateModelMock;
+
+    const TAX_RATE_ID = 1;
+
+    public function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->rateModelFactoryMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\RateFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->rateRegistry = $objectManager->getObject(
+            'Magento\Tax\Model\Calculation\RateRegistry',
+            ['taxModelRateFactory' => $this->rateModelFactoryMock]
+        );
+        $this->rateModelMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rate')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    public function testRegisterTaxRate()
+    {
+        $this->rateModelMock->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(self::TAX_RATE_ID));
+        $this->rateRegistry->registerTaxRate($this->rateModelMock);
+        $this->assertEquals($this->rateModelMock, $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID));
+    }
+
+    public function testRetrieveTaxRate()
+    {
+        $this->rateModelMock->expects($this->once())
+            ->method('load')
+            ->with(self::TAX_RATE_ID)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateModelMock->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(self::TAX_RATE_ID));
+        $this->rateModelFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($this->rateModelMock));
+
+        $actual = $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID);
+        $this->assertEquals($this->rateModelMock, $actual);
+
+        $actualCached = $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID);
+        $this->assertSame($actual, $actualCached);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testRetrieveException()
+    {
+        $this->rateModelMock->expects($this->once())
+            ->method('load')
+            ->with(self::TAX_RATE_ID)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateModelMock->expects($this->any())
+            ->method('getId')
+            ->will($this->returnValue(null));
+        $this->rateModelFactoryMock->expects($this->once())
+            ->method('create')
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID);
+    }
+
+    public function testRemoveTaxRate()
+    {
+        $this->rateModelMock->expects($this->any())
+            ->method('load')
+            ->with(self::TAX_RATE_ID)
+            ->will($this->returnValue($this->rateModelMock));
+
+        // The second time this is called, want it to return null indicating a new object
+        $this->rateModelMock->expects($this->any())
+            ->method('getId')
+            ->will($this->onConsecutiveCalls(self::TAX_RATE_ID, null));
+
+        $this->rateModelFactoryMock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->rateModelMock));
+
+        $actual = $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID);
+        $this->assertEquals($this->rateModelMock, $actual);
+
+        // Remove the rate
+        $this->rateRegistry->removeTaxRate(self::TAX_RATE_ID);
+
+        // Verify that if the rate is retrieved again, an exception is thrown
+        try {
+            $this->rateRegistry->retrieveTaxRate(self::TAX_RATE_ID);
+            $this->fail('NoSuchEntityException was not thrown as expected');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRateId',
+                'fieldValue' => self::TAX_RATE_ID,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TaxRuleRegistryTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TaxRuleRegistryTest.php
new file mode 100644
index 00000000000..a7bbdae4a6d
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Model/Calculation/TaxRuleRegistryTest.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Tax\Model\Calculation;
+
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestFramework\Helper\ObjectManager;
+
+/**
+ * Test for TaxRuleRegistry
+ *
+ */
+class TaxRuleRegistryTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Tax\Model\Calculation\TaxRuleRegistry
+     */
+    private $taxRuleRegistry;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\RuleFactory
+     */
+    private $taxRuleModelFactoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\Rule
+     */
+    private $taxRuleModelMock;
+
+    const TAX_RULE_ID = 1;
+
+    public function setUp()
+    {
+        $objectManager = new ObjectManager($this);
+        $this->taxRuleModelFactoryMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\RuleFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->taxRuleRegistry = $objectManager->getObject(
+            'Magento\Tax\Model\Calculation\TaxRuleRegistry',
+            ['taxRuleModelFactory' => $this->taxRuleModelFactoryMock]
+        );
+        $this->taxRuleModelMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rule')
+            ->disableOriginalConstructor()
+            ->getMock();
+    }
+
+    public function testRemoveTaxRule()
+    {
+        $this->taxRuleModelMock->expects($this->any())
+            ->method('load')
+            ->with(self::TAX_RULE_ID)
+            ->will($this->returnValue($this->taxRuleModelMock));
+
+        $this->taxRuleModelMock->expects($this->any())
+            ->method('getId')
+            ->will($this->onConsecutiveCalls(self::TAX_RULE_ID, null));
+
+        $this->taxRuleModelFactoryMock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->taxRuleModelMock));
+        $this->taxRuleRegistry->registerTaxRule($this->taxRuleModelMock);
+        $expected = $this->taxRuleRegistry->retrieveTaxRule(self::TAX_RULE_ID);
+        $this->assertEquals($this->taxRuleModelMock, $expected);
+
+        // Remove the tax rule
+        $this->taxRuleRegistry->removeTaxRule(self::TAX_RULE_ID);
+
+        // Verify that if the tax rule is retrieved again, an exception is thrown
+        try {
+            $this->taxRuleRegistry->retrieveTaxRule(self::TAX_RULE_ID);
+            $this->fail('NoSuchEntityException was not thrown as expected');
+        } catch (NoSuchEntityException $e) {
+            $expectedParams = [
+                'fieldName' => 'taxRuleId',
+                'fieldValue' => self::TAX_RULE_ID,
+            ];
+            $this->assertEquals($expectedParams, $e->getParameters());
+        }
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
new file mode 100644
index 00000000000..af61c181098
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRateServiceTest.php
@@ -0,0 +1,295 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1;
+
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Tax\Model\Calculation\Rate as RateModel;
+use Magento\Tax\Service\V1\Data\TaxRate;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class TaxRateServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var TaxRateServiceInterface
+     */
+    private $taxRateService;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\RateRegistry
+     */
+    private $rateRegistryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\Rate\Converter
+     */
+    private $converterMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\Rate
+     */
+    private $rateModelMock;
+
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    public function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+        $this->rateRegistryMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\RateRegistry')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->converterMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rate\Converter')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->rateModelMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rate')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->taxRateService = $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\TaxRateService',
+            [
+                'rateRegistry' => $this->rateRegistryMock,
+                'converter' => $this->converterMock,
+            ]
+        );
+    }
+
+    public function testCreateTaxRate()
+    {
+        $taxData = [
+            'country_id' => 'US',
+            'region_id' => '8',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate',
+            'zip_range' => ['from' => 78765, 'to' => 78780]
+        ];
+
+        $zipRangeBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        $taxRateBuilder = $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\Data\TaxRateBuilder',
+            ['zipRangeBuilder' => $zipRangeBuilder]
+        );
+
+        $taxRateDataObject = $taxRateBuilder->populateWithArray($taxData)->create();
+        $this->rateModelMock->expects($this->once())
+            ->method('save')
+            ->will($this->returnValue($this->rateModelMock));
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateModel')
+            ->will($this->returnValue($this->rateModelMock));
+        $taxRate = $taxRateBuilder->populate($taxRateDataObject)->setPostcode('78765-78780')->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateDataObjectFromModel')
+            ->will($this->returnValue($taxRate));
+
+        $taxRateServiceData = $this->taxRateService->createTaxRate($taxRateDataObject);
+
+        //Assertion
+        $this->assertSame($taxRate, $taxRateServiceData);
+
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     * @expectedExceptionMessage country_id is a required field.
+     */
+    public function testCreateTaxRateWithInputException()
+    {
+        $taxData = [
+            'country_id' => '',
+            'region_id' => '8',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate',
+            'zip_range' => ['from' => 78765, 'to' => 78780]
+        ];
+        $zipRangeBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        $taxRateBuilder = $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\Data\TaxRateBuilder',
+            ['zipRangeBuilder' => $zipRangeBuilder]
+        );
+        $taxRateDataObject = $taxRateBuilder->populateWithArray($taxData)->create();
+        $this->taxRateService->createTaxRate($taxRateDataObject);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Model\Exception
+     */
+    public function testCreateTaxRateWithModelException()
+    {
+        $taxData = [
+            'country_id' => 'US',
+            'region_id' => '8',
+            'percentage_rate' => '8.25',
+            'code' => 'US-CA-*-Rate',
+            'zip_range' => ['from' => 78765, 'to' => 78780]
+        ];
+        $zipRangeBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\ZipRangeBuilder');
+        $taxRateBuilder = $this->objectManager->getObject(
+            'Magento\Tax\Service\V1\Data\TaxRateBuilder',
+            ['zipRangeBuilder' => $zipRangeBuilder]
+        );
+        $taxRateDataObject = $taxRateBuilder->populateWithArray($taxData)->create();
+        $this->rateModelMock->expects($this->once())
+            ->method('save')
+            ->will($this->throwException(new \Magento\Framework\Model\Exception()));
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateModel')
+            ->will($this->returnValue($this->rateModelMock));
+        $this->taxRateService->createTaxRate($taxRateDataObject);
+    }
+
+    public function testGetTaxRate()
+    {
+        $taxRateDataObjectMock = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxRate')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->rateRegistryMock->expects($this->once())
+            ->method('retrieveTaxRate')
+            ->with(1)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateDataObjectFromModel')
+            ->with($this->rateModelMock)
+            ->will($this->returnValue($taxRateDataObjectMock));
+        $this->assertEquals($taxRateDataObjectMock, $this->taxRateService->getTaxRate(1));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     * @expectedExceptionMessage No such entity with taxRateId = 1
+     */
+    public function testGetTaxRateWithNoSuchEntityException()
+    {
+        $rateId = 1;
+        $this->rateRegistryMock->expects($this->once())
+            ->method('retrieveTaxRate')
+            ->with($rateId)
+            ->will($this->throwException(NoSuchEntityException::singleField('taxRateId', $rateId)));
+        $this->converterMock->expects($this->never())
+            ->method('createTaxRateDataObjectFromModel');
+        $this->taxRateService->getTaxRate($rateId);
+    }
+
+    public function testUpdateTaxRate()
+    {
+        $taxRateBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $taxRate = $taxRateBuilder
+            ->setId(2)
+            ->setCode('Rate-Code')
+            ->setCountryId('US')
+            ->setPercentageRate(0.1)
+            ->setPostcode('55555')
+            ->setRegionId('TX')
+            ->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateModel')
+            ->with($taxRate)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateModelMock->expects($this->once())->method('save');
+
+        $result = $this->taxRateService->updateTaxRate($taxRate);
+
+        $this->assertTrue($result);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testUpdateTaxRateNoId()
+    {
+        $taxRateBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $taxRate = $taxRateBuilder
+            ->setCode('Rate-Code')
+            ->setCountryId('US')
+            ->setPercentageRate(0.1)
+            ->setPostcode('55555')
+            ->setRegionId('TX')
+            ->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRateModel')
+            ->with($taxRate)
+            ->will($this->throwException(new NoSuchEntityException()));
+
+        $this->taxRateService->updateTaxRate($taxRate);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testUpdateTaxRateMissingRequiredInfo()
+    {
+        $taxRateBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRateBuilder');
+        $taxRate = $taxRateBuilder
+            ->setId(2)
+            ->setCode('Rate-Code')
+            ->setCountryId('US')
+            ->setPercentageRate(0.1)
+            ->setRegionId('TX')
+            ->create();
+
+        $this->taxRateService->updateTaxRate($taxRate);
+    }
+
+    public function testDeleteTaxRate()
+    {
+        $this->rateRegistryMock->expects($this->once())
+            ->method('retrieveTaxRate')
+            ->with(1)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateRegistryMock->expects($this->once())
+            ->method('removeTaxRate')
+            ->with(1)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->taxRateService->deleteTaxRate(1);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testDeleteTaxRateRetrieveException()
+    {
+        $this->rateRegistryMock->expects($this->once())
+            ->method('retrieveTaxRate')
+            ->with(1)
+            ->will($this->throwException(new NoSuchEntityException()));
+        $this->taxRateService->deleteTaxRate(1);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Bad error occurred
+     */
+    public function testDeleteTaxRateDeleteException()
+    {
+        $this->rateRegistryMock->expects($this->once())
+            ->method('retrieveTaxRate')
+            ->with(1)
+            ->will($this->returnValue($this->rateModelMock));
+        $this->rateModelMock->expects($this->once())
+            ->method('delete')
+            ->will($this->throwException(new \Exception('Bad error occurred')));
+        $this->taxRateService->deleteTaxRate(1);
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
new file mode 100644
index 00000000000..5426cf1d65f
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Tax/Service/V1/TaxRuleServiceTest.php
@@ -0,0 +1,325 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+namespace Magento\Tax\Service\V1;
+
+use Magento\Framework\Exception\ErrorMessage;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\TestFramework\Helper\ObjectManager;
+
+class TaxRuleServiceTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var TaxRuleServiceInterface
+     */
+    private $taxRuleService;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\TaxRuleRegistry
+     */
+    private $ruleRegistryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\TaxRuleConverter
+     */
+    private $converterMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Tax\Model\Calculation\Rule
+     */
+    private $ruleModelMock;
+
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
+    public function setUp()
+    {
+        $this->objectManager = new ObjectManager($this);
+        $this->ruleRegistryMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\TaxRuleRegistry')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->converterMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\TaxRuleConverter')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->ruleModelMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rule')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->taxRuleService = $this->objectManager->getObject('Magento\Tax\Service\V1\TaxRuleService',
+            [
+                'taxRuleRegistry' => $this->ruleRegistryMock,
+                'converter' => $this->converterMock,
+            ]
+        );
+    }
+
+    public function testDeleteTaxRule()
+    {
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('retrieveTaxRule')
+            ->with(1)
+            ->will($this->returnValue($this->ruleModelMock));
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('removeTaxRule')
+            ->with(1);
+        $this->taxRuleService->deleteTaxRule(1);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testDeleteTaxRuleRetrieveException()
+    {
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('retrieveTaxRule')
+            ->with(1)
+            ->will($this->throwException(new NoSuchEntityException()));
+        $this->taxRuleService->deleteTaxRule(1);
+    }
+
+    /**
+     * @expectedException \Exception
+     * @expectedExceptionMessage Bad error occurred
+     */
+    public function testDeleteTaxRuleDeleteException()
+    {
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('retrieveTaxRule')
+            ->with(1)
+            ->will($this->returnValue($this->ruleModelMock));
+        $this->ruleModelMock->expects($this->once())
+            ->method('delete')
+            ->will($this->throwException(new \Exception('Bad error occurred')));
+        $this->taxRuleService->deleteTaxRule(1);
+    }
+
+    public function testUpdateTaxRate()
+    {
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder
+            ->setId(2)
+            ->setCode('code')
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleModel')
+            ->with($taxRule)
+            ->will($this->returnValue($this->ruleModelMock));
+        $this->ruleModelMock->expects($this->once())->method('save');
+
+        $result = $this->taxRuleService->updateTaxRule($taxRule);
+
+        $this->assertTrue($result);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testUpdateTaxRuleNoId()
+    {
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder
+            ->setCode('code')
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleModel')
+            ->with($taxRule)
+            ->will($this->throwException(new NoSuchEntityException()));
+
+        $this->taxRuleService->updateTaxRule($taxRule);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testUpdateTaxRuleMissingRequiredInfo()
+    {
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder
+            ->setId(3)
+            ->setCode(null)
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+        $this->taxRuleService->updateTaxRule($taxRule);
+    }
+
+    public function testGetTaxRule()
+    {
+        $ruleId = 1;
+        $expectedTaxRule = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxRule')
+            ->disableOriginalConstructor()->getMock();
+        $taxRuleModel = $this->getMockBuilder('Magento\Tax\Model\Calculation\Rule')
+            ->disableOriginalConstructor()->getMock();
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('retrieveTaxRule')->with($ruleId)
+            ->will($this->returnValue($taxRuleModel));
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleDataObjectFromModel')->with($taxRuleModel)
+            ->will($this->returnValue($expectedTaxRule));
+
+        $taxRule = $this->taxRuleService->getTaxRule($ruleId);
+
+        $this->assertSame($expectedTaxRule, $taxRule);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+     */
+    public function testGetTaxRuleNotFound()
+    {
+        $ruleId = 1;
+        $this->ruleRegistryMock->expects($this->once())
+            ->method('retrieveTaxRule')->with($ruleId)
+            ->will($this->throwException(new NoSuchEntityException()));
+
+        $this->taxRuleService->getTaxRule($ruleId);
+    }
+
+    public function testCreateTaxRule()
+    {
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder
+            ->setId(2)
+            ->setCode('code')
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleModel')
+            ->with($taxRule)
+            ->will($this->returnValue($this->ruleModelMock));
+        $this->ruleModelMock->expects($this->once())->method('save');
+        $expectedTaxRule = $this->getMockBuilder('Magento\Tax\Service\V1\Data\TaxRule')
+            ->disableOriginalConstructor()->getMock();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleDataObjectFromModel')->with($this->ruleModelMock)
+            ->will($this->returnValue($expectedTaxRule));
+
+        $result = $this->taxRuleService->createTaxRule($taxRule);
+
+        $this->assertSame($expectedTaxRule, $result);
+    }
+
+    /**
+     * @dataProvider createTaxRuleMissingRequiredInfoDataProvider
+     * @expectedException \Magento\Framework\Exception\InputException
+     */
+    public function testCreateTaxRuleMissingRequiredInfo($data, $expectedMessages)
+    {
+        /** @var \Magento\Tax\Service\V1\Data\TaxRuleBuilder $taxRuleBuilder */
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder->populateWithArray($data)->create();
+
+        try {
+            $this->taxRuleService->createTaxRule($taxRule);
+        } catch (InputException $e) {
+            $errorMessages = array_map(
+                function ($error) {
+                    /** @var ErrorMessage $error */
+                    return $error->getMessage();
+                },
+                $e->getErrors()
+            );
+            $this->assertEquals($expectedMessages, $errorMessages);
+            throw $e;
+        }
+    }
+
+    public function createTaxRuleMissingRequiredInfoDataProvider()
+    {
+        return [
+            'empty fields' => [
+                [],
+                [
+                    'sort_order is a required field.',
+                    'priority is a required field.',
+                    'code is a required field.',
+                    'customer_tax_class_ids is a required field.',
+                    'product_tax_class_ids is a required field.',
+                    'tax_rate_ids is a required field.',
+                ],
+            ],
+            'negative fields' => [
+                [
+                    'id' => 3,
+                    'customer_tax_class_ids' => [3],
+                    'product_tax_class_ids' => [2],
+                    'tax_rate_ids' => [1],
+                    'code' => 'code',
+                    'sort_order' => -14,
+                    'priority' => -7,
+                ],
+                [
+                    'The sort_order value of "-14" must be greater than or equal to 0.',
+                    'The priority value of "-7" must be greater than or equal to 0.',
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testCreateTaxRuleExceptionOnSave()
+    {
+        $taxRuleBuilder = $this->objectManager->getObject('Magento\Tax\Service\V1\Data\TaxRuleBuilder');
+        $taxRule = $taxRuleBuilder
+            ->setId(2)
+            ->setCode('code')
+            ->setCustomerTaxClassIds([3])
+            ->setProductTaxClassIds([2])
+            ->setTaxRateIds([2])
+            ->setPriority(0)
+            ->setSortOrder(1)
+            ->create();
+        $this->converterMock->expects($this->once())
+            ->method('createTaxRuleModel')
+            ->with($taxRule)
+            ->will($this->returnValue($this->ruleModelMock));
+        $this->ruleModelMock->expects($this->once())
+            ->method('save')
+            ->will($this->throwException(new \Exception()));
+
+        $this->taxRuleService->createTaxRule($taxRule);
+    }
+
+}
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessorTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessorTest.php
new file mode 100644
index 00000000000..6d19b6f9bcb
--- /dev/null
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Controller/Rest/Response/PartialResponseProcessorTest.php
@@ -0,0 +1,271 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright  Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Webapi\Controller\Rest\Response;
+
+/**
+ * Unit test for PartialResponseProcessor
+ */
+class PartialResponseProcessorTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var PartialResponseProcessor SUT
+     */
+    protected $processor;
+
+    /**
+     * @var string
+     */
+    protected $sampleResponseValue;
+
+    /** @var \Magento\Webapi\Controller\Rest\Request|\PHPUnit_Framework_MockObject_MockObject */
+    protected $requestMock;
+
+    /**
+     * Setup SUT
+     */
+    public function setUp()
+    {
+        $this->requestMock = $this->getMock('Magento\Webapi\Controller\Rest\Request', [], [], '', false);
+        $this->processor = new PartialResponseProcessor($this->requestMock);
+        $this->sampleResponseValue = array(
+            'customer' =>
+                array(
+                    'id' => '1',
+                    'website_id' => '0',
+                    'created_in' => 'Default Store View',
+                    'store_id' => '1',
+                    'group_id' => '1',
+                    'custom_attributes' =>
+                        array(
+                            0 =>
+                                array(
+                                    'attribute_code' => 'disable_auto_group_change',
+                                    'value' => '0',
+                                ),
+                        ),
+                    'firstname' => 'Jane',
+                    'lastname' => 'Doe',
+                    'email' => 'jdoe@ebay.com',
+                    'default_billing' => '1',
+                    'default_shipping' => '1',
+                    'created_at' => '2014-05-27 18:59:43',
+                    'dob' => '1983-05-26 00:00:00',
+                    'taxvat' => '1212121212',
+                    'gender' => '1',
+                ),
+            'addresses' =>
+                array(
+                    0 =>
+                        array(
+                            'firstname' => 'Jane',
+                            'lastname' => 'Doe',
+                            'street' =>
+                                array(
+                                    0 => '7700  Parmer ln',
+                                ),
+                            'city' => 'Austin',
+                            'country_id' => 'US',
+                            'region' =>
+                                array(
+                                    'region' => 'Texas',
+                                    'region_id' => 57,
+                                    'region_code' => 'TX',
+                                ),
+                            'postcode' => '78728',
+                            'telephone' => '1111111111',
+                            'default_billing' => true,
+                            'default_shipping' => true,
+                            'id' => '1',
+                            'customer_id' => '1',
+                        ),
+                    1 =>
+                        array(
+                            'firstname' => 'Jane',
+                            'lastname' => 'Doe',
+                            'street' =>
+                                array(
+                                    0 => '2211 N First St ',
+                                ),
+                            'city' => 'San Jose',
+                            'country_id' => 'US',
+                            'region' =>
+                                array(
+                                    'region' => 'California',
+                                    'region_id' => 23,
+                                    'region_code' => 'CA',
+                                ),
+                            'postcode' => '98454',
+                            'telephone' => '2222222222',
+                            'default_billing' => true,
+                            'default_shipping' => true,
+                            'id' => '2',
+                            'customer_id' => '1',
+                        ),
+                ),
+        );
+    }
+
+    public function testFilterNoNesting()
+    {
+        $expected = array('customer' => $this->sampleResponseValue['customer']);
+
+        $simpleFilter = 'customer';
+        $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValue($simpleFilter));
+        $filteredResponse = $this->processor->filter($this->sampleResponseValue);
+
+        $this->assertEquals($expected, $filteredResponse);
+    }
+
+    public function testFilterSimpleNesting()
+    {
+        $expected = array(
+            'customer' => [
+                'email' => $this->sampleResponseValue['customer']['email'],
+                'id' => $this->sampleResponseValue['customer']['id']
+            ]
+        );
+
+        $simpleFilter = "customer[email,id]";
+
+        $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValue($simpleFilter));
+        $filteredResponse = $this->processor->filter($this->sampleResponseValue);
+
+        $this->assertEquals($expected, $filteredResponse);
+    }
+
+    public function testFilterMultilevelNesting()
+    {
+        $expected = array(
+            'customer' =>
+                array(
+                    'id' => '1',
+                    'email' => 'jdoe@ebay.com',
+                ),
+            'addresses' =>
+                array(
+                    0 =>
+                        array(
+                            'city' => 'Austin',
+                            'region' =>
+                                array(
+                                    'region' => 'Texas',
+                                    'region_code' => 'TX',
+                                ),
+                            'postcode' => '78728',
+                        ),
+                    1 =>
+                        array(
+                            'city' => 'San Jose',
+                            'region' =>
+                                array(
+                                    'region' => 'California',
+                                    'region_code' => 'CA',
+                                ),
+                            'postcode' => '98454',
+                        ),
+                ),
+        );
+
+        $nestedFilter = 'customer[id,email],addresses[city,postcode,region[region_code,region]]';
+
+        $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValue($nestedFilter));
+        $filteredResponse = $this->processor->filter($this->sampleResponseValue);
+
+        $this->assertEquals($expected, $filteredResponse);
+    }
+
+    public function testNonExistentFieldFilter()
+    {
+        //TODO : Make sure if this behavior is acceptable
+        $expected = array(
+            'customer' =>
+                array(
+                    'id' => '1',
+                    'email' => 'jdoe@ebay.com',
+                ),
+            'addresses' =>
+                array(
+                    0 =>
+                        array(
+                            //'city' => 'Austin', //City has been substituted with 'invalid' field
+                            'region' =>
+                                array(
+                                    'region' => 'Texas',
+                                    'region_code' => 'TX',
+                                ),
+                            'postcode' => '78728',
+                        ),
+                    1 =>
+                        array(
+                            //'city' => 'San Jose',
+                            'region' =>
+                                array(
+                                    'region' => 'California',
+                                    'region_code' => 'CA',
+                                ),
+                            'postcode' => '98454',
+                        ),
+                ),
+        );
+
+        $nonExistentFieldFilter = 'customer[id,email],addresses[invalid,postcode,region[region_code,region]]';
+
+        $this->requestMock
+            ->expects($this->any())
+            ->method('getParam')
+            ->will($this->returnValue($nonExistentFieldFilter));
+        $filteredResponse = $this->processor->filter($this->sampleResponseValue);
+
+        $this->assertEquals($expected, $filteredResponse);
+    }
+
+    /**
+     * @dataProvider invalidFilterDataProvider
+     */
+    public function testInvalidFilters($invalidFilter)
+    {
+        $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValue($invalidFilter));
+        $filteredResponse = $this->processor->filter($this->sampleResponseValue);
+
+        $this->assertEmpty($filteredResponse);
+    }
+
+    /**
+     * Data provider for invalid Filters
+     *
+     * @return array
+     */
+    public function invalidFilterDataProvider()
+    {
+        return [
+            ['  '],
+            [null],
+            ['customer(email)'],
+            [' customer[email]'],
+            ['-'],
+            ['customer[id,email],addresses[city,postcode,region[region_code,region]'] //Missing last parentheses
+        ];
+    }
+}
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
index 505a19c7d9e..f703703fadd 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.php
@@ -26,33 +26,66 @@ return [
         'Magento\Customer\Service\V1\CustomerServiceInterface' => [
             'getCustomer' => [
                 'resources' => [
-                    'Magento_Customer::customer_self' => true,
-                    'Magento_Customer::read' => true,
+                    0 => [
+                        'Magento_Customer::customer_self'
+                    ],
+                    1 => [
+                        'Magento_Customer::customer_self'
+                    ],
+                    2 => [
+                        'Magento_Customer::read'
+                    ],
                 ],
                 'secure' => false,
             ],
             'updateCustomer' => [
                 'resources' => [
-                    'Magento_Customer::customer_self' => true,
+                    0 => [
+                        'Magento_Customer::customer_self'
+                    ]
                 ],
                 'secure' => true,
             ],
             'createCustomer' => [
                 'resources' => [
-                    'Magento_Customer::manage' => true,
+                    0 => [
+                        'Magento_Customer::manage'
+                    ]
                 ],
                 'secure' => false,
             ],
             'deleteCustomer' => [
                 'resources' => [
-                    'Magento_Customer::manage' => true,
-                    'Magento_Customer::delete' => true,
+                    0 => [
+                        'Magento_Customer::manage',
+                        'Magento_Customer::delete'
+                    ]
                 ],
                 'secure' => false,
             ],
         ],
     ],
     'routes' => [
+        '/V1/customers/me/session' => [
+            'GET' => [
+                'secure' => false,
+                'service' => [
+                    'class' => 'Magento\Customer\Service\V1\CustomerServiceInterface',
+                    'method' => 'getCustomer',
+                ],
+                'resources' => [
+                    'Magento_Customer::customer_self' => true,
+                ],
+                'parameters' => [
+                    'id' => [
+                        'force' => true,
+                        'source' => 'session',
+                        'method' => 'getUserId',
+                        'value' => null,
+                    ],
+                ],
+            ],
+        ],
         '/V1/customers/me' => [
             'GET' => [
                 'secure' => false,
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.xml b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.xml
index d596a3c78d0..122d07975bd 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.xml
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Config/_files/webapi.xml
@@ -34,6 +34,15 @@
             <parameter name="id" force="true">null</parameter>
         </data>
     </route>
+    <route url="/V1/customers/me/session" method="GET">
+        <service class="Magento\Customer\Service\V1\CustomerServiceInterface" method="getCustomer" />
+        <resources>
+            <resource ref="Magento_Customer::customer_self" />
+        </resources>
+        <data>
+            <parameter name="id" force="true" source="session" method="getUserId">null</parameter>
+        </data>
+    </route>
     <route url="/V1/customers/me" method="PUT" secure="true">
         <service class="Magento\Customer\Service\V1\CustomerServiceInterface" method="updateCustomer" />
         <resources>
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/IntegrationServiceV1Test.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/IntegrationServiceV1Test.php
index 948f8cd65c8..ce96df7e150 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/IntegrationServiceV1Test.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/IntegrationServiceV1Test.php
@@ -66,7 +66,7 @@ class IntegrationServiceV1Test extends \PHPUnit_Framework_TestCase
         )->disableOriginalConstructor()->setMethods(
             array('create')
         )->getMock();
-        $this->subjectMock = $this->getMock('Magento\Integration\Service\IntegrationV1', array(), array(), '', false);
+        $this->subjectMock = $this->getMock('Magento\Integration\Service\V1\Integration', array(), array(), '', false);
         $this->integrationV1Plugin = new \Magento\Webapi\Model\Plugin\IntegrationServiceV1(
             $this->authzServiceMock,
             $this->userIdentifierFactoryMock
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/SetupTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/SetupTest.php
index 785edda04f5..1a2f385c36e 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/SetupTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Plugin/SetupTest.php
@@ -38,7 +38,7 @@ class SetupTest extends \PHPUnit_Framework_TestCase
     /**
      * Integration service mock
      *
-     * @var \Magento\Integration\Service\IntegrationV1Interface
+     * @var \Magento\Integration\Service\V1\IntegrationInterface
      */
     protected $integrationServiceMock;
 
@@ -77,7 +77,7 @@ class SetupTest extends \PHPUnit_Framework_TestCase
         )->getMock();
 
         $this->integrationServiceMock = $this->getMockBuilder(
-            '\Magento\Integration\Service\IntegrationV1'
+            '\Magento\Integration\Service\V1\Integration'
         )->disableOriginalConstructor()->setMethods(
             array('findByName')
         )->getMock();
diff --git a/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
index 1bc398f5f24..7c703764140 100644
--- a/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
+++ b/dev/tests/unit/testsuite/Magento/Webapi/Model/Soap/ConfigTest.php
@@ -67,7 +67,9 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
                 'Magento\Framework\Module\Service\FooV1Interface' => [
                     'someMethod' => [
                         'resources' => [
-                            'Magento_TestModule1::resource1' => true,
+                            [
+                                'Magento_TestModule1::resource1'
+                            ]
                         ],
                         'secure' => false,
                     ],
@@ -75,7 +77,9 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
                 'Magento\Framework\Module\Service\BarV1Interface' => [
                     'someMethod' => [
                         'resources' => [
-                            'Magento_TestModule1::resource2' => true,
+                            [
+                                'Magento_TestModule1::resource2'
+                            ]
                         ],
                         'secure' => false,
                     ],
@@ -115,7 +119,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
                         'method' => 'someMethod',
                         'inputRequired' => '',
                         'isSecure' => '',
-                        'resources' => array('Magento_TestModule1::resource1')
+                        'resources' => array(array('Magento_TestModule1::resource1'))
                     )
                 ),
                 'class' => 'Magento\Framework\Module\Service\FooV1Interface'
@@ -131,7 +135,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
             'class' => 'Magento\Framework\Module\Service\BarV1Interface',
             'method' => 'someMethod',
             'isSecure' => false,
-            'resources' => array('Magento_TestModule1::resource2')
+            'resources' => array(array('Magento_TestModule1::resource2'))
         );
         $methodInfo = $this->_soapConfig->getServiceMethodInfo(
             'moduleBarV1SomeMethod',
diff --git a/lib/internal/Magento/Framework/App/Filesystem.php b/lib/internal/Magento/Framework/App/Filesystem.php
index 7feeae89ef8..7f2e54059dc 100644
--- a/lib/internal/Magento/Framework/App/Filesystem.php
+++ b/lib/internal/Magento/Framework/App/Filesystem.php
@@ -68,7 +68,7 @@ class Filesystem extends \Magento\Framework\Filesystem
     const LIB_WEB = 'lib_web';
 
     /**
-     * Files with translation of system labels and messages from en_US to other languages
+     * Language packages
      */
     const LOCALE_DIR = 'i18n';
 
diff --git a/lib/internal/Magento/Framework/App/Filesystem/DirectoryList.php b/lib/internal/Magento/Framework/App/Filesystem/DirectoryList.php
index 03496995a94..bb23e7cb07d 100644
--- a/lib/internal/Magento/Framework/App/Filesystem/DirectoryList.php
+++ b/lib/internal/Magento/Framework/App/Filesystem/DirectoryList.php
@@ -67,7 +67,7 @@ class DirectoryList extends \Magento\Framework\Filesystem\DirectoryList
         Filesystem::DI_DIR => array('path' => 'var/di'),
         Filesystem::GENERATION_DIR => array('path' => 'var/generation'),
         Filesystem::HTTP => array('path' => ''),
-        Filesystem::LOCALE_DIR => array('path' => ''),
+        Filesystem::LOCALE_DIR => array('path' => 'app/i18n'),
         Filesystem::SYS_TMP_DIR => array(
             'path' => '',
             'read_only' => false,
diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php
new file mode 100644
index 00000000000..02357f2c0b5
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\App\Language;
+
+/**
+ * A service for reading language package dictionaries
+ */
+class Dictionary
+{
+    /**
+     * @var \Magento\Framework\Filesystem\Directory\ReadInterface
+     */
+    private $dir;
+
+    /**
+     * @var array
+     */
+    private $packs = array();
+
+    /**
+     * @param \Magento\Framework\App\Filesystem $filesystem
+     */
+    public function __construct(\Magento\Framework\App\Filesystem $filesystem)
+    {
+        $this->dir = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem::LOCALE_DIR);
+    }
+
+    /**
+     * Load and merge all phrases from language packs by specified code
+     *
+     * Takes into account inheritance between language packs
+     * Returns associative array where key is phrase in the source code and value is its translation
+     *
+     * @param string $languageCode
+     * @return array
+     */
+    public function getDictionary($languageCode)
+    {
+        $declarations = $this->dir->search('*/*/language.xml');
+        foreach ($declarations as $file) {
+            list($vendor, $code) = explode('/', $file);
+            if ($languageCode == $code) {
+                $this->readPackDeclaration($vendor, $code);
+            }
+        }
+        $packs = [];
+        $this->collectInheritedPacks($languageCode, $packs);
+        uasort($packs, [$this, 'sortInherited']);
+        $result = [];
+        foreach ($packs as $info) {
+            $dictionary = $this->readPackCsv($info['vendor'], $info['code']);
+            $result = array_merge($result, $dictionary);
+        }
+        return $result;
+    }
+
+    /**
+     * Read declaration of the specified language pack
+     *
+     * Will recursively load any parent packs
+     *
+     * @param string $vendor
+     * @param string $code
+     * @return void
+     */
+    private function readPackDeclaration($vendor, $code)
+    {
+        if (isset($this->packs[$code][$vendor])) {
+            return;
+        }
+        $file = "{$vendor}/{$code}/language.xml";
+        $dom = new \DOMDocument();
+        $xml = $this->dir->readFile($file);
+        $dom->loadXML($xml);
+        $root = $dom->documentElement;
+        $this->assertVendor($vendor, $root);
+        $this->assertCode($code, $root);
+        $this->packs[$code][$vendor] = [
+            'vendor' => $vendor,
+            'code' => $code,
+            'sort_order' => $this->getSortOrder($root),
+        ];
+        $use = $this->getUse($root);
+        if ($use) {
+            foreach ($use as $info) {
+                $this->packs[$code][$vendor]['use'][] = $info;
+                $this->readPackDeclaration($info['vendor'], $info['code']);
+            }
+        }
+    }
+
+    /**
+     * Assert that vendor code in the declaration matches the one discovered in file system
+     *
+     * @param string $expected
+     * @param \DOMElement $root
+     * @return void
+     * @throws \LogicException
+     */
+    public static function assertVendor($expected, \DOMElement $root)
+    {
+        foreach ($root->getElementsByTagName('vendor') as $node) {
+            if ($expected != $node->nodeValue) {
+                throw new \LogicException('Vendor name mismatch');
+            }
+            break;
+        }
+    }
+
+    /**
+     * Assert that language code in the declaration matches the one discovered in file system
+     *
+     * @param string $expected
+     * @param \DOMElement $root
+     * @return void
+     * @throws \LogicException
+     */
+    public static function assertCode($expected, \DOMElement $root)
+    {
+        foreach ($root->getElementsByTagName('code') as $node) {
+            if ($expected != $node->nodeValue) {
+                throw new \LogicException('Language code name mismatch');
+            }
+            break;
+        }
+    }
+
+    /**
+     * Read sort order from the declaration
+     *
+     * By default will be 0
+     *
+     * @param \DOMElement $root
+     * @return int
+     */
+    private function getSortOrder(\DOMElement $root)
+    {
+        foreach ($root->getElementsByTagName('sort_order') as $node) {
+            return (int)$node->nodeValue;
+        }
+        return 0;
+    }
+
+    /**
+     * Read information about reusing other packs from the declaration
+     *
+     * @param \DOMElement $root
+     * @return array
+     */
+    private function getUse(\DOMElement $root)
+    {
+        $result = [];
+        foreach ($root->getElementsByTagName('use') as $parent) {
+            $result[] = [
+                'vendor' => $parent->getAttribute('vendor'),
+                'code' => $parent->getAttribute('code'),
+            ];
+        }
+        return $result;
+    }
+
+    /**
+     * Line up (flatten) a tree of inheritance of language packs
+     *
+     * Record level of recursion (level of inheritance) for further use in sorting
+     *
+     * @param string $code
+     * @param array $result
+     * @param int $level
+     * @return void
+     */
+    private function collectInheritedPacks($code, array &$result, $level = 0)
+    {
+        if (isset($this->packs[$code])) {
+            foreach ($this->packs[$code] as $vendor => $info) {
+                $info['inheritance_level'] = $level;
+                $result["{$code}|{$vendor}"] = $info;
+                if (isset($info['use'])) {
+                    foreach ($info['use'] as $reuse) {
+                        $this->collectInheritedPacks($reuse['code'], $result, $level + 1);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sub-routine for custom sorting packs using inheritance level and sort order
+     *
+     * First sort by inheritance level descending, then by sort order ascending
+     *
+     * @param array $a
+     * @param array $b
+     * @return int
+     * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
+     */
+    private function sortInherited($a, $b)
+    {
+        if ($a['inheritance_level'] > $b['inheritance_level']) {
+            return -1;
+        }
+        if ($a['inheritance_level'] < $b['inheritance_level']) {
+            return 1;
+        }
+        if ($a['sort_order'] > $b['sort_order']) {
+            return 1;
+        }
+        if ($a['sort_order'] < $b['sort_order']) {
+            return -1;
+        }
+        return 0;
+    }
+
+    /**
+     * Read the CSV-files in a language package
+     *
+     * The files are sorted alphabetically, then each of them is read, and results are recorded into key => value array
+     *
+     * @param string $vendor
+     * @param string $code
+     * @return array
+     */
+    private function readPackCsv($vendor, $code)
+    {
+        $files = $this->dir->search("{$vendor}/{$code}/*.csv");
+        sort($files);
+        $result = [];
+        foreach ($files as $path) {
+            $file = $this->dir->openFile($path);
+            while (($row = $file->readCsv()) !== false) {
+                $result[$row[0]] = $row[1];
+            }
+        }
+        return $result;
+    }
+}
diff --git a/app/code/Magento/Core/etc/locale.xsd b/lib/internal/Magento/Framework/App/Language/package.xsd
similarity index 51%
rename from app/code/Magento/Core/etc/locale.xsd
rename to lib/internal/Magento/Framework/App/Language/package.xsd
index f8b521331de..8eb7aa87c5e 100644
--- a/app/code/Magento/Core/etc/locale.xsd
+++ b/lib/internal/Magento/Framework/App/Language/package.xsd
@@ -24,41 +24,34 @@
  */
 -->
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-    <xs:element name="config">
-        <xs:complexType>
-            <xs:sequence>
-                <xs:element name="locale" type="localeDeclaration" minOccurs="1" maxOccurs="unbounded" />
-            </xs:sequence>
-        </xs:complexType>
-        <xs:unique name="uniqueLocaleCode">
-            <xs:annotation>
-                <xs:documentation>
-                    Locale code must be unique.
-                </xs:documentation>
-            </xs:annotation>
-            <xs:selector xpath="locale"/>
-            <xs:field xpath="@code"/>
-        </xs:unique>
-    </xs:element>
+    <xs:element name="language" type="languageDeclarationType"/>
 
-    <xs:complexType name="localeDeclaration">
+    <xs:complexType name="languageDeclarationType">
         <xs:annotation>
-            <xs:documentation>
-                Locale declaration.
-            </xs:documentation>
+            <xs:documentation>Magento language package declaration</xs:documentation>
         </xs:annotation>
-        <xs:attribute name="code" type="localeCode" use="required" />
-        <xs:attribute name="parent" type="localeCode" use="required" />
+        <xs:sequence>
+            <xs:element minOccurs="1" maxOccurs="1" name="code" type="codeType"/>
+            <xs:element minOccurs="1" maxOccurs="1" name="vendor" type="vendorType"/>
+            <xs:element minOccurs="0" maxOccurs="1" name="sort_order" type="xs:integer"/>
+            <xs:element minOccurs="0" maxOccurs="1" name="use" type="useType"/>
+        </xs:sequence>
     </xs:complexType>
 
-    <xs:simpleType name="localeCode">
-        <xs:annotation>
-            <xs:documentation>
-                Locale code attribute can contain only [A-Za-z0-9_.-].
-            </xs:documentation>
-        </xs:annotation>
+    <xs:simpleType name="codeType">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[a-z]{2}_[A-Z]{2}"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="vendorType">
         <xs:restriction base="xs:string">
-            <xs:pattern value="[0-9a-zA-Z_\-.]+" />
+            <xs:pattern value="[A-Z][A-Za-z]+"/>
         </xs:restriction>
     </xs:simpleType>
+
+    <xs:complexType name="useType">
+        <xs:attribute use="required" name="vendor" type="vendorType"/>
+        <xs:attribute use="required" name="code" type="codeType"/>
+    </xs:complexType>
 </xs:schema>
diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php
index 0c82cf557f8..c1adafc34e5 100644
--- a/lib/internal/Magento/Framework/AppInterface.php
+++ b/lib/internal/Magento/Framework/AppInterface.php
@@ -35,7 +35,7 @@ interface AppInterface
     /**
      * Magento version
      */
-    const VERSION = '2.0.0.0-dev83';
+    const VERSION = '2.0.0.0-dev84';
 
     /**
      * Launch application
diff --git a/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php b/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php
index 5976baa95ee..5b756a3c195 100644
--- a/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php
+++ b/lib/internal/Magento/Framework/Archive/Helper/File/Bz.php
@@ -31,10 +31,14 @@ class Bz extends \Magento\Framework\Archive\Helper\File
 {
     /**
      * {@inheritdoc}
+     * @throws \RuntimeException
      */
     protected function _open($mode)
     {
-        $this->_fileHandler = @bzopen($this->_filePath, $mode);
+        if (!extension_loaded('bz2')) {
+            throw new \RuntimeException('PHP extension bz2 is required.');
+        }
+        $this->_fileHandler = bzopen($this->_filePath, $mode);
 
         if (false === $this->_fileHandler) {
             throw new \Magento\Framework\Exception('Failed to open file ' . $this->_filePath);
@@ -46,7 +50,7 @@ class Bz extends \Magento\Framework\Archive\Helper\File
      */
     protected function _write($data)
     {
-        $result = @bzwrite($this->_fileHandler, $data);
+        $result = bzwrite($this->_fileHandler, $data);
 
         if (false === $result) {
             throw new \Magento\Framework\Exception('Failed to write data to ' . $this->_filePath);
diff --git a/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php b/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php
index 003bdd90b86..9f4fa7865a3 100644
--- a/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php
+++ b/lib/internal/Magento/Framework/Archive/Helper/File/Gz.php
@@ -31,10 +31,14 @@ class Gz extends \Magento\Framework\Archive\Helper\File
 {
     /**
      * {@inheritdoc}
+     * @throws \RuntimeException
      */
     protected function _open($mode)
     {
-        $this->_fileHandler = @gzopen($this->_filePath, $mode);
+        if (!extension_loaded('zlib')) {
+            throw new \RuntimeException('PHP extension zlib is required.');
+        }
+        $this->_fileHandler = gzopen($this->_filePath, $mode);
 
         if (false === $this->_fileHandler) {
             throw new \Magento\Framework\Exception('Failed to open file ' . $this->_filePath);
@@ -46,7 +50,7 @@ class Gz extends \Magento\Framework\Archive\Helper\File
      */
     protected function _write($data)
     {
-        $result = @gzwrite($this->_fileHandler, $data);
+        $result = gzwrite($this->_fileHandler, $data);
 
         if (empty($result) && !empty($data)) {
             throw new \Magento\Framework\Exception('Failed to write data to ' . $this->_filePath);
diff --git a/lib/internal/Magento/Framework/Config/etc/theme.xsd b/lib/internal/Magento/Framework/Config/etc/theme.xsd
index bd0f6cfa1eb..445af22b235 100644
--- a/lib/internal/Magento/Framework/Config/etc/theme.xsd
+++ b/lib/internal/Magento/Framework/Config/etc/theme.xsd
@@ -56,7 +56,7 @@
 
     <xs:simpleType name="version">
         <xs:restriction base="xs:string">
-            <xs:pattern value="(\d+.\d+.\d+.\d+(\-[a-zA-Z0-9]+)?)|\*"></xs:pattern>
+            <xs:pattern value="(\d+.\d+.\d+(\-[a-zA-Z0-9]+)?)|\*"></xs:pattern>
         </xs:restriction>
     </xs:simpleType>
 
diff --git a/lib/internal/Magento/Framework/Convert/Excel.php b/lib/internal/Magento/Framework/Convert/Excel.php
index 1298579bce8..97a4f56a189 100644
--- a/lib/internal/Magento/Framework/Convert/Excel.php
+++ b/lib/internal/Magento/Framework/Convert/Excel.php
@@ -150,7 +150,7 @@ class Excel
 
         foreach ($row as $value) {
             $value = htmlspecialchars($value);
-            $dataType = is_numeric($value) ? 'Number' : 'String';
+            $dataType = is_numeric($value) && $value[0] !== '+' && $value[0] !== '0' ? 'Number' : 'String';
 
             $value = str_replace("\r\n", '&#10;', $value);
             $value = str_replace("\r", '&#10;', $value);
diff --git a/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php b/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
index 3bcfcb2e1bc..3d605691e98 100644
--- a/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
+++ b/lib/internal/Magento/Framework/Filter/Input/MaliciousCode.php
@@ -42,13 +42,13 @@ class MaliciousCode implements \Zend_Filter_Interface
         //import styles
         '/(@import)/Usi',
         //js in the style attribute
-        '/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis',
+        '/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\/*\>)/Uis',
         //js attributes
-        '/(ondblclick|onclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onload|onunload|onerror)=[^<]*(?=\>)/Uis',
+        '/(ondblclick|onclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onload|onunload|onerror)=[^<]*(?=\/*\>)/Uis',
         //tags
         '/<\/?(script|meta|link|frame|iframe).*>/Uis',
         //base64 usage
-        '/src=[^<]*base64[^<]*(?=\>)/Uis'
+        '/src=[^<]*base64[^<]*(?=\/*\>)/Uis'
     );
 
     /**
diff --git a/lib/internal/Magento/Framework/Filter/Object/Grid.php b/lib/internal/Magento/Framework/Filter/Object/Grid.php
index fb573e003c2..b968823dbac 100644
--- a/lib/internal/Magento/Framework/Filter/Object/Grid.php
+++ b/lib/internal/Magento/Framework/Filter/Object/Grid.php
@@ -35,8 +35,8 @@ class Grid extends \Magento\Framework\Filter\Object
     {
         $out = array();
         if (is_array($grid)) {
-            foreach ($grid as $i => $array) {
-                $out[$i] = parent::filter($array);
+            foreach ($grid as $key => $gridItem) {
+                $out[$key] = parent::filter($gridItem);
             }
         }
         return $out;
diff --git a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Converter.php b/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Converter.php
deleted file mode 100644
index f710343d0b4..00000000000
--- a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Converter.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * Locale hierarchy configuration converter
- *
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy\Config;
-
-class Converter implements \Magento\Framework\Config\ConverterInterface
-{
-    /**
-     * Compose locale inheritance hierarchy based on given config
-     *
-     * @param array $localeConfig assoc array where key is a code of locale and value is a code of its parent locale
-     * @return array
-     */
-    protected function _composeLocaleHierarchy($localeConfig)
-    {
-        $localeHierarchy = array();
-        foreach ($localeConfig as $locale => $localeParent) {
-            $localeParents = array($localeParent);
-            while (isset(
-                $localeConfig[$localeParent]
-            ) && !in_array(
-                $localeConfig[$localeParent],
-                $localeParents
-            ) && $locale != $localeConfig[$localeParent]) {
-                // inheritance chain starts with the deepest parent
-                array_unshift($localeParents, $localeConfig[$localeParent]);
-                $localeParent = $localeConfig[$localeParent];
-            }
-            // scope hierarchy for current locale
-            $localeHierarchy[$locale] = $localeParents;
-        }
-        return $localeHierarchy;
-    }
-
-    /**
-     * Convert dom node tree to array
-     *
-     * @param \DOMDocument $source
-     * @return array
-     */
-    public function convert($source)
-    {
-        $output = array();
-        /** @var \DOMNodeList $locales */
-        $locales = $source->getElementsByTagName('locale');
-        /** @var \DOMNode $locale */
-        foreach ($locales as $locale) {
-            $parent = $locale->attributes->getNamedItem('parent');
-            if ($parent) {
-                $output[$locale->attributes->getNamedItem('code')->nodeValue] = $parent->nodeValue;
-            }
-        }
-        return $this->_composeLocaleHierarchy($output);
-    }
-}
diff --git a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/FileResolver.php b/lib/internal/Magento/Framework/Locale/Hierarchy/Config/FileResolver.php
deleted file mode 100644
index 4a7dfbb574f..00000000000
--- a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/FileResolver.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Hierarchy config file resolver
- *
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy\Config;
-
-class FileResolver implements \Magento\Framework\Config\FileResolverInterface
-{
-    /**
-     * @var \Magento\Framework\Filesystem\Directory\ReadInterface
-     */
-    protected $directoryRead;
-
-    /**
-     * @var \Magento\Framework\Config\FileIteratorFactory
-     */
-    protected $iteratorFactory;
-
-    /**
-     * @param \Magento\Framework\App\Filesystem $filesystem
-     * @param \Magento\Framework\Config\FileIteratorFactory $iteratorFactory
-     */
-    public function __construct(
-        \Magento\Framework\App\Filesystem $filesystem,
-        \Magento\Framework\Config\FileIteratorFactory $iteratorFactory
-    ) {
-        $this->directoryRead = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem::APP_DIR);
-        $this->iteratorFactory = $iteratorFactory;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function get($filename, $scope)
-    {
-        $result = array();
-        if ($this->directoryRead->isExist('locale')) {
-            $result = $this->iteratorFactory->create(
-                $this->directoryRead,
-                $this->directoryRead->search('/locale/*/' . $filename)
-            );
-        }
-        return $result;
-    }
-}
diff --git a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Reader.php b/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Reader.php
deleted file mode 100644
index 8be96c44647..00000000000
--- a/lib/internal/Magento/Framework/Locale/Hierarchy/Config/Reader.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
- * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
- */
-namespace Magento\Framework\Locale\Hierarchy\Config;
-
-class Reader extends \Magento\Framework\Config\Reader\Filesystem
-{
-    /**
-     * List of id attributes for merge
-     *
-     * @var array
-     */
-    protected $_idAttributes = array('/config/locale' => 'code');
-
-    /**
-     * @param FileResolver $fileResolver
-     * @param Converter $converter
-     * @param SchemaLocator $schemaLocator
-     * @param \Magento\Framework\Config\ValidationStateInterface $validationState
-     * @param string $fileName
-     * @param array $idAttributes
-     * @param string $domDocumentClass
-     * @param string $defaultScope
-     */
-    public function __construct(
-        \Magento\Framework\Locale\Hierarchy\Config\FileResolver $fileResolver,
-        \Magento\Framework\Locale\Hierarchy\Config\Converter $converter,
-        \Magento\Framework\Locale\Hierarchy\Config\SchemaLocator $schemaLocator,
-        \Magento\Framework\Config\ValidationStateInterface $validationState,
-        $fileName = 'config.xml',
-        $idAttributes = array(),
-        $domDocumentClass = 'Magento\Framework\Config\Dom',
-        $defaultScope = 'global'
-    ) {
-        parent::__construct(
-            $fileResolver,
-            $converter,
-            $schemaLocator,
-            $validationState,
-            $fileName,
-            $idAttributes,
-            $domDocumentClass,
-            $defaultScope
-        );
-    }
-}
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 303608539ae..753fca0b6da 100644
--- a/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php
+++ b/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php
@@ -318,7 +318,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
             }
 
             foreach ($field as $key => $value) {
-                $this->addFieldToSelect($value, is_string($key) ? $key : null, false);
+                $this->addFieldToSelect($value, is_string($key) ? $key : null);
             }
 
             $this->_fieldsToSelectChanged = true;
@@ -375,17 +375,18 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
         if ($isAlias) {
             if (isset($this->_fieldsToSelect[$field])) {
                 unset($this->_fieldsToSelect[$field]);
+                $this->_fieldsToSelectChanged = true;
             }
         } else {
             foreach ($this->_fieldsToSelect as $key => $value) {
                 if ($value === $field) {
                     unset($this->_fieldsToSelect[$key]);
+                    $this->_fieldsToSelectChanged = true;
                     break;
                 }
             }
         }
 
-        $this->_fieldsToSelectChanged = true;
         return $this;
     }
 
@@ -433,10 +434,9 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db
     /**
      * Get model instance
      *
-     * @param array $args
      * @return string
      */
-    public function getModelName($args = array())
+    public function getModelName()
     {
         return $this->_model;
     }
diff --git a/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php b/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php
index 8369428e7ca..02fcca1f218 100644
--- a/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php
+++ b/lib/internal/Magento/Framework/Module/Declaration/Converter/Dom.php
@@ -44,11 +44,11 @@ class Dom implements \Magento\Framework\Config\ConverterInterface
                 throw new \Exception('Attribute "name" is required for module node.');
             }
             $moduleData['name'] = $nameNode->nodeValue;
-            $versionNode = $moduleAttributes->getNamedItem('version');
+            $versionNode = $moduleAttributes->getNamedItem('schema_version');
             if (is_null($versionNode)) {
-                throw new \Exception('Attribute "version" is required for module node.');
+                throw new \Exception('Attribute "schema_version" is required for module node.');
             }
-            $moduleData['version'] = $versionNode->nodeValue;
+            $moduleData['schema_version'] = $versionNode->nodeValue;
             $activeNode = $moduleAttributes->getNamedItem('active');
             if (is_null($activeNode)) {
                 throw new \Exception('Attribute "active" is required for module node.');
diff --git a/lib/internal/Magento/Framework/Module/Setup.php b/lib/internal/Magento/Framework/Module/Setup.php
index a6e91d6b2dc..bd4c35dd6d8 100644
--- a/lib/internal/Magento/Framework/Module/Setup.php
+++ b/lib/internal/Magento/Framework/Module/Setup.php
@@ -209,7 +209,7 @@ class Setup implements \Magento\Framework\Module\Updater\SetupInterface
     public function applyDataUpdates()
     {
         $dataVer = $this->_resourceResource->getDataVersion($this->_resourceName);
-        $configVer = $this->_moduleConfig['version'];
+        $configVer = $this->_moduleConfig['schema_version'];
         if ($dataVer !== false) {
             $status = version_compare($configVer, $dataVer);
             if ($status == self::VERSION_COMPARE_GREATER) {
@@ -229,7 +229,7 @@ class Setup implements \Magento\Framework\Module\Updater\SetupInterface
     public function applyUpdates()
     {
         $dbVer = $this->_resourceResource->getDbVersion($this->_resourceName);
-        $configVer = $this->_moduleConfig['version'];
+        $configVer = $this->_moduleConfig['schema_version'];
 
         // Module is installed
         if ($dbVer !== false) {
diff --git a/lib/internal/Magento/Framework/Module/etc/module.xsd b/lib/internal/Magento/Framework/Module/etc/module.xsd
index a4162174a83..913bc99678c 100644
--- a/lib/internal/Magento/Framework/Module/etc/module.xsd
+++ b/lib/internal/Magento/Framework/Module/etc/module.xsd
@@ -72,7 +72,7 @@
             </xs:element>
         </xs:all>
         <xs:attribute name="name" type="moduleName" use="required" />
-        <xs:attribute name="version" type="moduleVersion" use="optional" />
+        <xs:attribute name="schema_version" type="schemaVersion" use="optional" />
         <xs:attribute name="active" type="xs:boolean" use="optional" />
     </xs:complexType>
 
@@ -162,10 +162,10 @@
         </xs:restriction>
     </xs:simpleType>
 
-    <xs:simpleType name="moduleVersion">
+    <xs:simpleType name="schemaVersion">
         <xs:annotation>
             <xs:documentation>
-                Module version attribute can contain only [0-9.].
+                Schema version attribute can contain only [0-9.].
             </xs:documentation>
         </xs:annotation>
         <xs:restriction base="xs:string">
diff --git a/lib/internal/Magento/Framework/Oauth/Exception.php b/lib/internal/Magento/Framework/Oauth/Exception.php
index 74646be9b33..47493b4c23a 100644
--- a/lib/internal/Magento/Framework/Oauth/Exception.php
+++ b/lib/internal/Magento/Framework/Oauth/Exception.php
@@ -24,25 +24,11 @@
 
 namespace Magento\Framework\Oauth;
 
+use Magento\Framework\Exception\AuthenticationException;
+
 /**
- * oAuth \Exception
+ * OAuth \Exception
  */
-class Exception extends \Magento\Webapi\Exception
+class Exception extends AuthenticationException
 {
-    /**
-     * @param string $message
-     * @param int $code
-     * @param int $httpCode
-     * @param array $details
-     * @param string $name
-     */
-    public function __construct(
-        $message,
-        $code = 0,
-        $httpCode = self::HTTP_UNAUTHORIZED,
-        array $details = array(),
-        $name = 'oauth'
-    ) {
-        parent::__construct($message, $code, $httpCode, $details, $name);
-    }
 }
diff --git a/lib/internal/Magento/Framework/Oauth/Helper/Request.php b/lib/internal/Magento/Framework/Oauth/Helper/Request.php
index b9b5c31ceac..403dceeff52 100644
--- a/lib/internal/Magento/Framework/Oauth/Helper/Request.php
+++ b/lib/internal/Magento/Framework/Oauth/Helper/Request.php
@@ -23,8 +23,6 @@
  */
 namespace Magento\Framework\Oauth\Helper;
 
-use Magento\Framework\Oauth\OauthInterface;
-
 class Request
 {
     /**#@+
@@ -42,55 +40,6 @@ class Request
 
     /**#@-*/
 
-    /**
-     * Error code to error messages pairs
-     *
-     * @var array
-     */
-    protected $_errors = array(
-        OauthInterface::ERR_VERSION_REJECTED => 'version_rejected',
-        OauthInterface::ERR_PARAMETER_ABSENT => 'parameter_absent',
-        OauthInterface::ERR_PARAMETER_REJECTED => 'parameter_rejected',
-        OauthInterface::ERR_TIMESTAMP_REFUSED => 'timestamp_refused',
-        OauthInterface::ERR_NONCE_USED => 'nonce_used',
-        OauthInterface::ERR_SIGNATURE_METHOD_REJECTED => 'signature_method_rejected',
-        OauthInterface::ERR_SIGNATURE_INVALID => 'signature_invalid',
-        OauthInterface::ERR_CONSUMER_KEY_REJECTED => 'consumer_key_rejected',
-        OauthInterface::ERR_CONSUMER_KEY_INVALID => 'consumer_key_invalid',
-        OauthInterface::ERR_TOKEN_USED => 'token_used',
-        OauthInterface::ERR_TOKEN_EXPIRED => 'token_expired',
-        OauthInterface::ERR_TOKEN_REVOKED => 'token_revoked',
-        OauthInterface::ERR_TOKEN_REJECTED => 'token_rejected',
-        OauthInterface::ERR_VERIFIER_INVALID => 'verifier_invalid',
-        OauthInterface::ERR_PERMISSION_UNKNOWN => 'permission_unknown',
-        OauthInterface::ERR_PERMISSION_DENIED => 'permission_denied',
-        OauthInterface::ERR_METHOD_NOT_ALLOWED => 'method_not_allowed'
-    );
-
-    /**
-     * Error code to HTTP error code
-     *
-     * @var array
-     */
-    protected $_errorsToHttpCode = array(
-        OauthInterface::ERR_VERSION_REJECTED => self::HTTP_BAD_REQUEST,
-        OauthInterface::ERR_PARAMETER_ABSENT => self::HTTP_BAD_REQUEST,
-        OauthInterface::ERR_PARAMETER_REJECTED => self::HTTP_BAD_REQUEST,
-        OauthInterface::ERR_TIMESTAMP_REFUSED => self::HTTP_BAD_REQUEST,
-        OauthInterface::ERR_NONCE_USED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_SIGNATURE_METHOD_REJECTED => self::HTTP_BAD_REQUEST,
-        OauthInterface::ERR_SIGNATURE_INVALID => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_CONSUMER_KEY_REJECTED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_CONSUMER_KEY_INVALID => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_TOKEN_USED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_TOKEN_EXPIRED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_TOKEN_REVOKED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_TOKEN_REJECTED => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_VERIFIER_INVALID => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_PERMISSION_UNKNOWN => self::HTTP_UNAUTHORIZED,
-        OauthInterface::ERR_PERMISSION_DENIED => self::HTTP_UNAUTHORIZED
-    );
-
     /**
      * Process HTTP request object and prepare for token validation
      *
@@ -256,28 +205,14 @@ class Request
      */
     public function prepareErrorResponse(\Exception $exception, \Zend_Controller_Response_Http $response = null)
     {
-        $errorMap = $this->_errors;
-        $errorsToHttpCode = $this->_errorsToHttpCode;
-
-        $eMsg = $exception->getMessage();
+        $errorMsg = $exception->getMessage();
 
         if ($exception instanceof \Magento\Framework\Oauth\Exception) {
-            $eCode = $exception->getCode();
-
-            if (isset($errorMap[$eCode])) {
-                $errorMsg = $errorMap[$eCode];
-                $responseCode = $errorsToHttpCode[$eCode];
-            } else {
-                $errorMsg = 'unknown_problem&code=' . $eCode;
-                $responseCode = self::HTTP_INTERNAL_ERROR;
-            }
-            if (OauthInterface::ERR_PARAMETER_ABSENT == $eCode) {
-                $errorMsg .= '&oauth_parameters_absent=' . $eMsg;
-            } elseif ($eMsg) {
-                $errorMsg .= '&message=' . $eMsg;
-            }
+            $responseCode = self::HTTP_UNAUTHORIZED;
+        } elseif ($exception instanceof \Magento\Framework\Oauth\OauthInputException) {
+            $responseCode = self::HTTP_BAD_REQUEST;
         } else {
-            $errorMsg = 'internal_error&message=' . ($eMsg ? $eMsg : 'empty_message');
+            $errorMsg = 'internal_error&message=' . ($errorMsg ? $errorMsg : 'empty_message');
             $responseCode = self::HTTP_INTERNAL_ERROR;
         }
 
diff --git a/lib/internal/Magento/Framework/Oauth/Oauth.php b/lib/internal/Magento/Framework/Oauth/Oauth.php
index cd255c3c667..f5b3e368ebe 100644
--- a/lib/internal/Magento/Framework/Oauth/Oauth.php
+++ b/lib/internal/Magento/Framework/Oauth/Oauth.php
@@ -188,14 +188,14 @@ class Oauth implements OauthInterface
      * @param string $requestUrl
      * @param string $tokenSecret
      * @return void
-     * @throws Exception
+     * @throws Exception|OauthInputException
      */
     protected function _validateSignature($params, $consumerSecret, $httpMethod, $requestUrl, $tokenSecret = null)
     {
         if (!in_array($params['oauth_signature_method'], self::getSupportedSignatureMethods())) {
-            throw new Exception(
-                __('Signature method %1 is not supported', $params['oauth_signature_method']),
-                self::ERR_SIGNATURE_METHOD_REJECTED
+            throw new OauthInputException(
+                'Signature method %1 is not supported',
+                [$params['oauth_signature_method']]
             );
         }
 
@@ -212,7 +212,7 @@ class Oauth implements OauthInterface
         );
 
         if ($calculatedSign != $params['oauth_signature']) {
-            throw new Exception(__('Invalid signature'), self::ERR_SIGNATURE_INVALID);
+            throw new Exception('Invalid signature');
         }
     }
 
@@ -221,13 +221,13 @@ class Oauth implements OauthInterface
      *
      * @param string $version
      * @return void
-     * @throws Exception
+     * @throws OauthInputException
      */
     protected function _validateVersionParam($version)
     {
         // validate version if specified
         if ('1.0' != $version) {
-            throw new Exception(__('OAuth version %1 is not supported', $version), self::ERR_VERSION_REJECTED);
+            throw new OauthInputException('OAuth version %1 is not supported', [$version]);
         }
     }
 
@@ -237,7 +237,7 @@ class Oauth implements OauthInterface
      * @param array $protocolParams
      * @param array $requiredParams
      * @return void
-     * @throws Exception
+     * @throws Exception|OauthInputException
      */
     protected function _validateProtocolParams($protocolParams, $requiredParams)
     {
@@ -264,14 +264,14 @@ class Oauth implements OauthInterface
             $protocolParams['oauth_token']
         )
         ) {
-            throw new Exception(__('Token is not the correct length'), self::ERR_TOKEN_REJECTED);
+            throw new Exception('Token is not the correct length');
         }
 
         // Validate signature method.
         if (!in_array($protocolParams['oauth_signature_method'], self::getSupportedSignatureMethods())) {
-            throw new Exception(
-                __('Signature method %1 is not supported', $protocolParams['oauth_signature_method']),
-                self::ERR_SIGNATURE_METHOD_REJECTED
+            throw new OauthInputException(
+                'Signature method %1 is not supported',
+                [$protocolParams['oauth_signature_method']]
             );
         }
 
@@ -289,13 +289,13 @@ class Oauth implements OauthInterface
      * @param array $protocolParams
      * @param array $requiredParams
      * @return void
-     * @throws Exception
+     * @throws OauthInputException
      */
     protected function _checkRequiredParams($protocolParams, $requiredParams)
     {
         foreach ($requiredParams as $param) {
             if (!isset($protocolParams[$param])) {
-                throw new Exception($param, self::ERR_PARAMETER_ABSENT);
+                throw new OauthInputException(OauthInputException::REQUIRED_FIELD, ['fieldName' => $param]);
             }
         }
     }
diff --git a/lib/internal/Magento/Framework/Filter/GridArray/Grid.php b/lib/internal/Magento/Framework/Oauth/OauthInputException.php
similarity index 72%
rename from lib/internal/Magento/Framework/Filter/GridArray/Grid.php
rename to lib/internal/Magento/Framework/Oauth/OauthInputException.php
index 51b1b3ee75d..0f89c4fc69e 100644
--- a/lib/internal/Magento/Framework/Filter/GridArray/Grid.php
+++ b/lib/internal/Magento/Framework/Oauth/OauthInputException.php
@@ -21,20 +21,14 @@
  * @copyright  Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
  * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
-namespace Magento\Framework\Filter\GridArray;
 
-class Grid extends \Magento\Framework\Filter\ArrayFilter
+namespace Magento\Framework\Oauth;
+
+use Magento\Framework\Exception\InputException;
+
+/**
+ * OAuth \OAuthInputException
+ */
+class OauthInputException extends InputException
 {
-    /**
-     * @param array $grid
-     * @return array
-     */
-    public function filter($grid)
-    {
-        $out = array();
-        foreach ($grid as $i => $array) {
-            $out[$i] = parent::filter($array);
-        }
-        return $out;
-    }
 }
diff --git a/lib/internal/Magento/Framework/Service/V1/Data/AbstractSearchResultsBuilder.php b/lib/internal/Magento/Framework/Service/V1/Data/AbstractSearchResultsBuilder.php
new file mode 100644
index 00000000000..1db283676d3
--- /dev/null
+++ b/lib/internal/Magento/Framework/Service/V1/Data/AbstractSearchResultsBuilder.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Magento
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Open Software License (OSL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/osl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@magentocommerce.com so we can send you a copy immediately.
+ *
+ * DISCLAIMER
+ *
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
+ * versions in the future. If you wish to customize Magento for your
+ * needs please refer to http://www.magentocommerce.com for more information.
+ *
+ * @copyright   Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
+ * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
+ */
+
+namespace Magento\Framework\Service\V1\Data;
+
+use Magento\Framework\Service\Data\AbstractObjectBuilder;
+use Magento\Framework\Service\Data\ObjectFactory;
+
+/**
+ * Builder for the SearchResults Service Data Object
+ *
+ * @method SearchResults create()
+ */
+abstract class AbstractSearchResultsBuilder extends AbstractObjectBuilder
+{
+    /**
+     * Search criteria builder
+     *
+     * @var SearchCriteriaBuilder
+     */
+    protected $searchCriteriaBuilder;
+
+    /**
+     * Item data object builder
+     *
+     * @var AbstractObjectBuilder $itemObjectBuilder
+     */
+    protected $itemObjectBuilder;
+
+    /**
+     * Constructor
+     *
+     * @param ObjectFactory $objectFactory
+     * @param SearchCriteriaBuilder $searchCriteriaBuilder
+     * @param AbstractObjectBuilder $itemObjectBuilder
+     */
+    public function __construct(
+        ObjectFactory $objectFactory,
+        SearchCriteriaBuilder $searchCriteriaBuilder,
+        AbstractObjectBuilder $itemObjectBuilder
+    ) {
+        parent::__construct($objectFactory);
+        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+        $this->itemObjectBuilder = $itemObjectBuilder;
+    }
+
+    /**
+     * Set search criteria
+     *
+     * @param SearchCriteria $searchCriteria
+     * @return $this
+     */
+    public function setSearchCriteria(SearchCriteria $searchCriteria)
+    {
+        return $this->_set(SearchResults::KEY_SEARCH_CRITERIA, $searchCriteria);
+    }
+
+    /**
+     * Set total count
+     *
+     * @param int $totalCount
+     * @return $this
+     */
+    public function setTotalCount($totalCount)
+    {
+        return $this->_set(SearchResults::KEY_TOTAL_COUNT, $totalCount);
+    }
+
+    /**
+     * Set items
+     *
+     * @param \Magento\Framework\Service\Data\AbstractObject[] $items
+     * @return $this
+     */
+    public function setItems($items)
+    {
+        return $this->_set(SearchResults::KEY_ITEMS, $items);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function _setDataValues(array $data)
+    {
+        if (array_key_exists(SearchResults::KEY_SEARCH_CRITERIA, $data)) {
+            $data[SearchResults::KEY_SEARCH_CRITERIA] =
+                $this->searchCriteriaBuilder->populateWithArray($data[SearchResults::KEY_SEARCH_CRITERIA])->create();
+        }
+        if (array_key_exists(SearchResults::KEY_ITEMS, $data)) {
+            $items = [];
+            foreach ($data[SearchResults::KEY_ITEMS] as $itemArray) {
+                $items[] = $this->itemObjectBuilder->populateWithArray($itemArray)->create();
+            }
+            $data[SearchResults::KEY_ITEMS] = $items;
+        }
+        return parent::_setDataValues($data);
+    }
+}
diff --git a/app/code/Magento/Catalog/Service/V1/Data/SearchResults.php b/lib/internal/Magento/Framework/Service/V1/Data/SearchResults.php
similarity index 77%
rename from app/code/Magento/Catalog/Service/V1/Data/SearchResults.php
rename to lib/internal/Magento/Framework/Service/V1/Data/SearchResults.php
index 0f873ceda7a..33fb843ede4 100644
--- a/app/code/Magento/Catalog/Service/V1/Data/SearchResults.php
+++ b/lib/internal/Magento/Framework/Service/V1/Data/SearchResults.php
@@ -22,21 +22,25 @@
  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
 
-namespace Magento\Catalog\Service\V1\Data;
+namespace Magento\Framework\Service\V1\Data;
 
 /**
  * SearchResults Service Data Object used for the search service requests
  */
 class SearchResults extends \Magento\Framework\Service\Data\AbstractObject
 {
+    const KEY_ITEMS = 'items';
+    const KEY_SEARCH_CRITERIA = 'search_criteria';
+    const KEY_TOTAL_COUNT = 'total_count';
+
     /**
      * Get items
      *
-     * @return \Magento\Catalog\Service\V1\Data\Product[]
+     * @return \Magento\Framework\Service\Data\AbstractObject[]
      */
     public function getItems()
     {
-        return is_null($this->_get('items')) ? array() : $this->_get('items');
+        return is_null($this->_get(self::KEY_ITEMS)) ? [] : $this->_get(self::KEY_ITEMS);
     }
 
     /**
@@ -46,7 +50,7 @@ class SearchResults extends \Magento\Framework\Service\Data\AbstractObject
      */
     public function getSearchCriteria()
     {
-        return $this->_get('search_criteria');
+        return $this->_get(self::KEY_SEARCH_CRITERIA);
     }
 
     /**
@@ -56,6 +60,6 @@ class SearchResults extends \Magento\Framework\Service\Data\AbstractObject
      */
     public function getTotalCount()
     {
-        return $this->_get('total_count');
+        return $this->_get(self::KEY_TOTAL_COUNT);
     }
 }
diff --git a/lib/internal/Magento/Framework/Translate.php b/lib/internal/Magento/Framework/Translate.php
index 95cf2370ae5..6dd0d97c7a0 100644
--- a/lib/internal/Magento/Framework/Translate.php
+++ b/lib/internal/Magento/Framework/Translate.php
@@ -66,13 +66,6 @@ class Translate implements \Magento\Framework\TranslateInterface
      */
     protected $_dataScope;
 
-    /**
-     * Locale hierarchy (empty by default)
-     *
-     * @var array
-     */
-    protected $_localeHierarchy = [];
-
     /**
      * @var \Magento\Framework\View\DesignInterface
      */
@@ -133,9 +126,13 @@ class Translate implements \Magento\Framework\TranslateInterface
      */
     protected $_csvParser;
 
+    /**
+     * @var \Magento\Framework\App\Language\Dictionary
+     */
+    protected $packDictionary;
+
     /**
      * @param \Magento\Framework\View\DesignInterface $viewDesign
-     * @param \Magento\Framework\Locale\Hierarchy\Config $config
      * @param \Magento\Framework\Cache\FrontendInterface $cache
      * @param \Magento\Framework\View\FileSystem $viewFileSystem
      * @param \Magento\Framework\Module\ModuleList $moduleList
@@ -147,12 +144,12 @@ class Translate implements \Magento\Framework\TranslateInterface
      * @param \Magento\Framework\App\Filesystem $filesystem
      * @param \Magento\Framework\App\RequestInterface $request
      * @param \Magento\Framework\File\Csv $csvParser
+     * @param \Magento\Framework\App\Language\Dictionary $packDictionary
      *
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
         \Magento\Framework\View\DesignInterface $viewDesign,
-        \Magento\Framework\Locale\Hierarchy\Config $config,
         \Magento\Framework\Cache\FrontendInterface $cache,
         \Magento\Framework\View\FileSystem $viewFileSystem,
         \Magento\Framework\Module\ModuleList $moduleList,
@@ -163,7 +160,8 @@ class Translate implements \Magento\Framework\TranslateInterface
         \Magento\Framework\App\State $appState,
         \Magento\Framework\App\Filesystem $filesystem,
         \Magento\Framework\App\RequestInterface $request,
-        \Magento\Framework\File\Csv $csvParser
+        \Magento\Framework\File\Csv $csvParser,
+        \Magento\Framework\App\Language\Dictionary $packDictionary
     ) {
         $this->_viewDesign = $viewDesign;
         $this->_cache = $cache;
@@ -176,8 +174,8 @@ class Translate implements \Magento\Framework\TranslateInterface
         $this->_appState = $appState;
         $this->request = $request;
         $this->directory = $filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem::ROOT_DIR);
-        $this->_localeHierarchy = $config->getHierarchy();
         $this->_csvParser = $csvParser;
+        $this->packDictionary = $packDictionary;
     }
 
     /**
@@ -201,10 +199,9 @@ class Translate implements \Magento\Framework\TranslateInterface
         }
         $this->_data = [];
 
-        foreach ($this->_moduleList->getModules() as $module) {
-            $this->_loadModuleTranslation($module['name']);
-        }
+        $this->_loadModuleTranslation($forceReload);
         $this->_loadThemeTranslation($forceReload);
+        $this->_loadPackTranslation($forceReload);
         $this->_loadDbTranslation($forceReload);
 
         if (!$forceReload) {
@@ -263,34 +260,18 @@ class Translate implements \Magento\Framework\TranslateInterface
     /**
      * Load data from module translation files
      *
-     * @param string $moduleName
+     * @param bool $forceReload
      * @return $this
      */
-    protected function _loadModuleTranslation($moduleName)
+    protected function _loadModuleTranslation($forceReload = false)
     {
-        $requiredLocaleList = $this->_composeRequiredLocaleList($this->getLocale());
-        foreach ($requiredLocaleList as $locale) {
-            $moduleFilePath = $this->_getModuleTranslationFile($moduleName, $locale);
-            $this->_addData($this->_getFileData($moduleFilePath));
+        foreach ($this->_moduleList->getModules() as $module) {
+            $moduleFilePath = $this->_getModuleTranslationFile($module['name'], $this->getLocale());
+            $this->_addData($this->_getFileData($moduleFilePath), false, $forceReload);
         }
         return $this;
     }
 
-    /**
-     * Compose the list of locales which are required to translate text entity based on given locale
-     *
-     * @param string $locale
-     * @return string[]
-     */
-    protected function _composeRequiredLocaleList($locale)
-    {
-        $requiredLocaleList = array($locale);
-        if (isset($this->_localeHierarchy[$locale])) {
-            $requiredLocaleList = array_merge($this->_localeHierarchy[$locale], $requiredLocaleList);
-        }
-        return $requiredLocaleList;
-    }
-
     /**
      * Adding translation data
      *
@@ -342,16 +323,25 @@ class Translate implements \Magento\Framework\TranslateInterface
             return $this;
         }
 
-        $requiredLocaleList = $this->_composeRequiredLocaleList($this->getLocale());
-        foreach ($requiredLocaleList as $locale) {
-            $file = $this->_getThemeTranslationFile($locale);
-            if ($file) {
-                $this->_addData($this->_getFileData($file), 'theme' . $this->_config['theme'], $forceReload);
-            }
+        $file = $this->_getThemeTranslationFile($this->getLocale());
+        if ($file) {
+            $this->_addData($this->_getFileData($file), 'theme' . $this->_config['theme'], $forceReload);
         }
         return $this;
     }
 
+    /**
+     * Load translation dictionary from language packages
+     *
+     * @param bool $forceReload
+     * @return void
+     */
+    protected function _loadPackTranslation($forceReload = false)
+    {
+        $data = $this->packDictionary->getDictionary($this->getLocale());
+        $this->_addData($data, 'language_pack', $forceReload);
+    }
+
     /**
      * Loading current translation from DB
      *
@@ -360,11 +350,8 @@ class Translate implements \Magento\Framework\TranslateInterface
      */
     protected function _loadDbTranslation($forceReload = false)
     {
-        $requiredLocaleList = $this->_composeRequiredLocaleList($this->getLocale());
-        foreach ($requiredLocaleList as $locale) {
-            $arr = $this->_translateResource->getTranslationArray(null, $locale);
-            $this->_addData($arr, $this->getConfig('scope'), $forceReload);
-        }
+        $arr = $this->_translateResource->getTranslationArray(null, $this->getLocale());
+        $this->_addData($arr, $this->getConfig('scope'), $forceReload);
         return $this;
     }
 
@@ -377,7 +364,7 @@ class Translate implements \Magento\Framework\TranslateInterface
      */
     protected function _getModuleTranslationFile($moduleName, $locale)
     {
-        $file = $this->_modulesReader->getModuleDir(\Magento\Framework\App\Filesystem::LOCALE_DIR, $moduleName);
+        $file = $this->_modulesReader->getModuleDir('i18n', $moduleName);
         $file .= '/' . $locale . '.csv';
         return $file;
     }
@@ -391,7 +378,7 @@ class Translate implements \Magento\Framework\TranslateInterface
     protected function _getThemeTranslationFile($locale)
     {
         return $this->_viewFileSystem->getLocaleFileName(
-            \Magento\Framework\App\Filesystem::LOCALE_DIR . '/' . $locale . '.csv',
+            'i18n' . '/' . $locale . '.csv',
             ['area' => $this->getConfig('area')]
         );
     }
diff --git a/lib/internal/Magento/Framework/View/Design/Theme/Validator.php b/lib/internal/Magento/Framework/View/Design/Theme/Validator.php
index 98614cb1387..8699ad53792 100644
--- a/lib/internal/Magento/Framework/View/Design/Theme/Validator.php
+++ b/lib/internal/Magento/Framework/View/Design/Theme/Validator.php
@@ -73,7 +73,7 @@ class Validator
                 'name' => 'available',
                 'class' => 'Zend_Validate_Regex',
                 'break' => true,
-                'options' => array('pattern' => '/^(\d+\.\d+\.\d+\.\d+(\-[a-zA-Z0-9]+)?)$|^\*$/'),
+                'options' => array('pattern' => '/^(\d+\.\d+\.\d+(\-[a-zA-Z0-9]+)?)$|^\*$/'),
                 'message' => __('Theme version has not compatible format.')
             )
         );
diff --git a/lib/web/mage/adminhtml/form.js b/lib/web/mage/adminhtml/form.js
index 622da9ce948..6a94b447262 100644
--- a/lib/web/mage/adminhtml/form.js
+++ b/lib/web/mage/adminhtml/form.js
@@ -134,7 +134,8 @@ RegionUpdater.prototype = {
                 return;
             }
             var form = currentElement.form,
-                validationInstance = form ? jQuery(form).data('validation') : null;
+                validationInstance = form ? jQuery(form).data('validation') : null,
+                field = currentElement.up('.field') || new Element('div');
 
             if (validationInstance) {
                 validationInstance.clearError(currentElement);
@@ -161,6 +162,9 @@ RegionUpdater.prototype = {
             }
 
             if (!regionRequired || !currentElement.visible()) {
+                if (field.hasClassName('required')) {
+                    field.removeClassName('required');
+                }
                 if (currentElement.hasClassName('required-entry')) {
                     currentElement.removeClassName('required-entry');
                 }
@@ -170,6 +174,9 @@ RegionUpdater.prototype = {
                     currentElement.removeClassName('validate-select');
                 }
             } else {
+                if (!field.hasClassName('required')) {
+                    field.addClassName('required');
+                }
                 if (!currentElement.hasClassName('required-entry')) {
                     currentElement.addClassName('required-entry');
                 }
@@ -281,7 +288,7 @@ RegionUpdater.prototype = {
             }
         }
     }
-}
+};
 
 regionUpdater = RegionUpdater;
 
@@ -430,7 +437,9 @@ FormElementDependenceController.prototype = {
 
         // toggle target row
         var headElement = $(idTo + '-head'),
-            inputs = $(idTo).up(this._config.levels_up).select('input', 'select', 'td');
+            inputs = $(idTo).up(this._config.levels_up).select('input', 'select', 'td'),
+            isInheritCheckboxChecked = $(idTo + '_inherit') && $(idTo + '_inherit').checked,
+            isAnInputOrSelect = ['input', 'select'].indexOf($(idTo).tagName.toLowerCase()) != -1;
         if (shouldShowUp) {
             var currentConfig = this._config;
             if (inputs) {
@@ -452,7 +461,7 @@ FormElementDependenceController.prototype = {
                 }
             } else {
                 $(idTo).show();
-                if (['input', 'select'].indexOf($(idTo).tagName.toLowerCase()) != -1) {
+                if (isAnInputOrSelect) {
                     $(idTo).disabled = false;
                     jQuery('#' + idTo).removeClass('ignore-validate');
                 }
@@ -471,7 +480,7 @@ FormElementDependenceController.prototype = {
                 headElement.hide();
             }
             $(idTo).hide();
-            if (['input', 'select'].indexOf($(idTo).tagName.toLowerCase()) != -1) {
+            if (isAnInputOrSelect && !isInheritCheckboxChecked) {
                 $(idTo).disabled = true;
                 jQuery('#' + idTo).addClass('ignore-validate');
             }
diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js
index 771b713c901..9e7d5d8044f 100644
--- a/lib/web/mage/validation.js
+++ b/lib/web/mage/validation.js
@@ -42,6 +42,19 @@
                 return (value === '' || (value == null) || (value.length === 0));
             },
 
+
+            /**
+             * Checks if {value} is between numbers {from} and {to}
+             * @param {string} value
+             * @param {string} from
+             * @param {string} to
+             * @returns {boolean}
+             */
+            isBetween: function(value, from, to){
+                return (from === null || from === '' || value >= $.mage.parseNumber(from)) &&
+                       (to === null || to === '' || value <= $.mage.parseNumber(to));
+            },
+
             /**
              * Parse price string
              * @param {string}
@@ -614,7 +627,7 @@
             'Please enter a valid number in this field.'
         ],
         "validate-number-range": [
-            function(v, elm) {
+            function(v, elm, param) {
                 if ($.mage.isEmptyNoTrim(v)) {
                     return true;
                 }
@@ -624,18 +637,28 @@
                     return false;
                 }
 
-                var reRange = /^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,
-                    result = true;
-
-                var values = elm.className.split(" ");
+                var dataAttrRange = /^(-?[\d.,]+)?-(-?[\d.,]+)?$/,
+                    classNameRange = /^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,
+                    result = true,
+                    range, m, classes, ii;
 
-                for (var i = values.length - 1; i >= 0; i--) {
-                    var name = values[i];
-                    var m = reRange.exec(name);
+                range = param;
+                if (range) {
+                    m = dataAttrRange.exec(range);
                     if (m) {
-                        result = result &&
-                            (m[1] == null || m[1] === '' || numValue >= $.mage.parseNumber(m[1])) &&
-                            (m[2] == null || m[2] === '' || numValue <= $.mage.parseNumber(m[2]));
+                        result = result && $.mage.isBetween(numValue, m[1], m[2]);
+                    }
+                } else if (elm && elm.className ) {
+                    classes = elm.className.split(" ");
+                    ii = classes.length;
+
+                    while (ii--) {
+                        range = classes[ii];
+                        m = classNameRange.exec(range);
+                        if (m) {
+                            result = result && $.mage.isBetween(numValue, m[1], m[2]);
+                            break;
+                        }
                     }
                 }
 
@@ -650,7 +673,7 @@
             'Please enter a valid number in this field.'
         ],
         "validate-digits-range": [
-            function(v, elm) {
+            function(v, elm, param) {
                 if ($.mage.isEmptyNoTrim(v)) {
                     return true;
                 }
@@ -660,21 +683,31 @@
                     return false;
                 }
 
-                var reRange = /^digits-range-(-?\d+)?-(-?\d+)?$/,
-                    result = true;
-
-                var values = elm.className.split(" ");
-
-                for (var i = values.length - 1; i >= 0; i--) {
-                    var name = values[i];
-                    var m = reRange.exec(name);
+                var dataAttrRange = /^(-?\d+)?-(-?\d+)?$/,
+                    classNameRange = /^digits-range-(-?\d+)?-(-?\d+)?$/,
+                    result = true,
+                    range, m, classes, ii;
+                range = param;
+                if (range) {
+                    m = dataAttrRange.exec(range);
                     if (m) {
-                        result = result &&
-                            (m[1] == null || m[1] === '' || numValue >= $.mage.parseNumber(m[1])) &&
-                            (m[2] == null || m[2] === '' || numValue <= $.mage.parseNumber(m[2]));
+                        result = result && $.mage.isBetween(numValue, m[1], m[2]);
+                    }
+                } else if (elm && elm.className ) {
+                    classes = elm.className.split(" ");
+                    ii = classes.length;
+
+                    while (ii--) {
+                        range = classes[ii];
+                        m = classNameRange.exec(range);
+                        if (m) {
+                            result = result && $.mage.isBetween(numValue, m[1], m[2]);
+                            break;
+                        }
                     }
                 }
 
+
                 return result;
             },
             'The value is not within the specified range.'
@@ -1276,5 +1309,16 @@
             this.validate = this.element.validate(this.options);
         }
     });
+
+    $('form').on('invalid-form.validate', function (event, validation) {
+        var lastActive = $(validation.findLastActive() || validation.errorList.length && validation.errorList[0].element || []);
+        if (lastActive.is(':hidden')) {
+            var parent = lastActive.parent();
+            var windowHeight = $(window).height();
+            $('html, body').animate({
+                scrollTop: parent.offset().top - windowHeight / 2
+            });
+        }
+    });
 })(jQuery);
 
-- 
GitLab