diff --git a/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php
index b9ffb332e1cdd93e8c1597880e9a90b66281b2ee..ec1aeee42d175e30a30a4c2099b11f0d69215f89 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/BasePriceStorage.php
@@ -210,7 +210,11 @@ class BasePriceStorage implements \Magento\Catalog\Api\BasePriceStorageInterface
             } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
                 $this->validationResult->addFailedItem(
                     $id,
-                    __('Requested store is not found.')
+                    __(
+                        'Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId.',
+                        ['SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
+                    ),
+                    ['SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
                 );
             }
         }
diff --git a/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php b/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php
index d5f9d08e9115ddb72351cde957df3b8dce7bee57..6b2575d5eaf7faaed793b225ba4b6b8fd51e7574 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/CostStorage.php
@@ -190,10 +190,10 @@ class CostStorage implements \Magento\Catalog\Api\CostStorageInterface
                 $this->validationResult->addFailedItem(
                     $id,
                     __(
-                        'Invalid attribute %fieldName = %fieldValue.',
-                        ['fieldName' => '%fieldName', 'fieldValue' => '%fieldValue']
+                        'Invalid attribute Cost = %cost. Row ID: SKU = %SKU, Store ID: %storeId.',
+                        ['cost' => $price->getCost(), 'SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
                     ),
-                    ['fieldName' => 'Cost', 'fieldValue' => $price->getCost()]
+                    ['cost' => $price->getCost(), 'SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
                 );
             }
             try {
@@ -201,7 +201,11 @@ class CostStorage implements \Magento\Catalog\Api\CostStorageInterface
             } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
                 $this->validationResult->addFailedItem(
                     $id,
-                    __('Requested store is not found.')
+                    __(
+                        'Requested store is not found. Row ID: SKU = %SKU, Store ID: %storeId.',
+                        ['SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
+                    ),
+                    ['SKU' => $price->getSku(), 'storeId' => $price->getStoreId()]
                 );
             }
         }
diff --git a/app/code/Magento/Catalog/Model/Product/Price/InvalidSkuChecker.php b/app/code/Magento/Catalog/Model/Product/Price/InvalidSkuChecker.php
index 8eb7c1415c69367d984dfdb6a25d47091c626959..c6a34bb803980268c93625b3e1e627fbff46b849 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/InvalidSkuChecker.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/InvalidSkuChecker.php
@@ -34,7 +34,12 @@ class InvalidSkuChecker
     public function retrieveInvalidSkuList(array $skus, array $allowedProductTypes, $allowedPriceTypeValue = false)
     {
         $idsBySku = $this->productIdLocator->retrieveProductIdsBySkus($skus);
-        $skuDiff = array_diff($skus, array_keys($idsBySku));
+        $existingSkus = array_keys($idsBySku);
+        $skuDiff = array_udiff(
+            $skus,
+            $existingSkus,
+            'strcasecmp'
+        );
 
         foreach ($idsBySku as $sku => $ids) {
             foreach ($ids as $type) {
@@ -42,7 +47,7 @@ class InvalidSkuChecker
 
                 if ($allowedPriceTypeValue
                     && $type == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
-                    && $this->productRepository->get($sku)->getPriceType() != $allowedProductTypes
+                    && $this->productRepository->get($sku)->getPriceType() != $allowedPriceTypeValue
                 ) {
                     $valueTypeIsAllowed = true;
                 }
diff --git a/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php
index d3ec22571094d203b4a4fbc9ac9c578214d2725d..59220aaf22a1de0407ed355033474a7579f1327f 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/SpecialPriceStorage.php
@@ -143,21 +143,47 @@ class SpecialPriceStorage implements \Magento\Catalog\Api\SpecialPriceStorageInt
                 $this->validationResult->addFailedItem(
                     $key,
                     __(
-                        'Requested product doesn\'t exist: %sku',
-                        ['sku' => '%sku']
+                        'Requested product doesn\'t exist. '
+                        . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.',
+                        [
+                            'SKU' => $price->getSku(),
+                            'storeId' => $price->getStoreId(),
+                            'priceFrom' => $price->getPriceFrom(),
+                            'priceTo' => $price->getPriceTo()
+                        ]
                     ),
-                    ['sku' => $price->getSku()]
+                    [
+                        'SKU' => $price->getSku(),
+                        'storeId' => $price->getStoreId(),
+                        'priceFrom' => $price->getPriceFrom(),
+                        'priceTo' => $price->getPriceTo()
+                    ]
                 );
             }
-            $this->checkPrice($price->getPrice(), $key);
-            $this->checkDate($price->getPriceFrom(), 'Price From', $key);
-            $this->checkDate($price->getPriceTo(), 'Price To', $key);
+            $this->checkPrice($price, $key);
+            $this->checkDate($price, $price->getPriceFrom(), 'Price From', $key);
+            $this->checkDate($price, $price->getPriceTo(), 'Price To', $key);
             try {
                 $this->storeRepository->getById($price->getStoreId());
             } catch (NoSuchEntityException $e) {
                 $this->validationResult->addFailedItem(
                     $key,
-                    __('Requested store is not found.')
+                    __(
+                        'Requested store is not found. '
+                        . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.',
+                        [
+                            'SKU' => $price->getSku(),
+                            'storeId' => $price->getStoreId(),
+                            'priceFrom' => $price->getPriceFrom(),
+                            'priceTo' => $price->getPriceTo()
+                        ]
+                    ),
+                    [
+                        'SKU' => $price->getSku(),
+                        'storeId' => $price->getStoreId(),
+                        'priceFrom' => $price->getPriceFrom(),
+                        'priceTo' => $price->getPriceTo()
+                    ]
                 );
             }
         }
@@ -172,21 +198,35 @@ class SpecialPriceStorage implements \Magento\Catalog\Api\SpecialPriceStorageInt
     /**
      * Check that date value is correct and add error to aggregator if it contains incorrect data.
      *
+     * @param \Magento\Catalog\Api\Data\SpecialPriceInterface $price
      * @param string $value
      * @param string $label
      * @param int $key
      * @return void
      */
-    private function checkDate($value, $label, $key)
+    private function checkDate(\Magento\Catalog\Api\Data\SpecialPriceInterface $price, $value, $label, $key)
     {
         if ($value && !$this->isCorrectDateValue($value)) {
             $this->validationResult->addFailedItem(
                 $key,
                 __(
-                    'Invalid attribute %fieldName = %fieldValue.',
-                    ['fieldName' => '%fieldName', 'fieldValue' => '%fieldValue']
+                    'Invalid attribute %label = %priceTo. '
+                    . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.',
+                    [
+                        'label' => $label,
+                        'SKU' => $price->getSku(),
+                        'storeId' => $price->getStoreId(),
+                        'priceFrom' => $price->getPriceFrom(),
+                        'priceTo' => $price->getPriceTo()
+                    ]
                 ),
-                ['fieldName' => $label, 'fieldValue' => $value]
+                [
+                    'label' => $label,
+                    'SKU' => $price->getSku(),
+                    'storeId' => $price->getStoreId(),
+                    'priceFrom' => $price->getPriceFrom(),
+                    'priceTo' => $price->getPriceTo()
+                ]
             );
         }
     }
@@ -195,20 +235,33 @@ class SpecialPriceStorage implements \Magento\Catalog\Api\SpecialPriceStorageInt
      * Check that provided price value is not empty and not lower then zero and add error to aggregator if price
      * contains not valid data.
      *
-     * @param float $price
+     * @param \Magento\Catalog\Api\Data\SpecialPriceInterface $price
      * @param int $key
      * @return void
      */
-    private function checkPrice($price, $key)
+    private function checkPrice(\Magento\Catalog\Api\Data\SpecialPriceInterface $price, $key)
     {
-        if (null === $price || $price < 0) {
+        if (null === $price->getPrice() || $price->getPrice() < 0) {
             $this->validationResult->addFailedItem(
                 $key,
                 __(
-                    'Invalid attribute %fieldName = %fieldValue.',
-                    ['fieldName' => '%fieldName', 'fieldValue' => '%fieldValue']
+                    'Invalid attribute Price = %price. '
+                    . 'Row ID: SKU = %SKU, Store ID: %storeId, Price From: %priceFrom, Price To: %priceTo.',
+                    [
+                        'price' => $price->getPrice(),
+                        'SKU' => $price->getSku(),
+                        'storeId' => $price->getStoreId(),
+                        'priceFrom' => $price->getPriceFrom(),
+                        'priceTo' => $price->getPriceTo()
+                    ]
                 ),
-                ['fieldName' => 'Price', 'fieldValue' => $price]
+                [
+                    'price' => $price->getPrice(),
+                    'SKU' => $price->getSku(),
+                    'storeId' => $price->getStoreId(),
+                    'priceFrom' => $price->getPriceFrom(),
+                    'priceTo' => $price->getPriceTo()
+                ]
             );
         }
     }
@@ -216,14 +269,14 @@ class SpecialPriceStorage implements \Magento\Catalog\Api\SpecialPriceStorageInt
     /**
      * Retrieve SKU by product ID.
      *
-     * @param int $id
+     * @param int $productId
      * @param array $skus
-     * @return int|null
+     * @return string|null
      */
-    private function retrieveSkuById($id, array $skus)
+    private function retrieveSkuById($productId, array $skus)
     {
         foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $sku => $ids) {
-            if (false !== array_key_exists($id, $ids)) {
+            if (isset($ids[$productId])) {
                 return $sku;
             }
         }
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
index b8e78380bbc31bcb1f4c1cc525146f6e4314adef..8f2b16542b1ec6706ea5066408884459cd77bdab 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -259,7 +259,7 @@ class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
      *
      * @param array $price
      * @param array $existingPrices
-     * @return int|void
+     * @return int|null
      */
     private function retrievePriceId(array $price, array $existingPrices)
     {
@@ -275,6 +275,8 @@ class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
                 return $existingPrice['value_id'];
             }
         }
+
+        return null;
     }
 
     /**
diff --git a/app/code/Magento/Catalog/Model/ProductIdLocator.php b/app/code/Magento/Catalog/Model/ProductIdLocator.php
index 3cc6f931ec4cd6172f667469e23be42aa272394a..4a25d2603da38c165f0d9bec3a179999a29a16f5 100644
--- a/app/code/Magento/Catalog/Model/ProductIdLocator.php
+++ b/app/code/Magento/Catalog/Model/ProductIdLocator.php
@@ -95,6 +95,10 @@ class ProductIdLocator implements \Magento\Catalog\Model\ProductIdLocatorInterfa
             }
         }
 
-        return array_intersect_key($this->idsBySku, array_flip($skus));
+        return array_intersect_ukey(
+            $this->idsBySku,
+            array_flip($skus),
+            'strcasecmp'
+        );
     }
 }
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php
index 78f6c6540b6cb3487711c2d70949b2039ead5b14..a7c82b553365d4c8290e8b459a05a130d9d886eb 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/CostStorageTest.php
@@ -252,7 +252,7 @@ class CostStorageTest extends \PHPUnit_Framework_TestCase
     public function testUpdateWithNegativeCost()
     {
         $sku = 'sku_1';
-        $this->costInterface->expects($this->exactly(3))->method('getSku')->willReturn($sku);
+        $this->costInterface->expects($this->exactly(5))->method('getSku')->willReturn($sku);
         $this->invalidSkuChecker
             ->expects($this->exactly(1))
             ->method('retrieveInvalidSkuList')
@@ -267,7 +267,7 @@ class CostStorageTest extends \PHPUnit_Framework_TestCase
             ->with(['attributeCode' => 'cost'])
             ->willReturn($this->pricePersistence);
         $this->pricePersistence->expects($this->atLeastOnce())->method('update');
-        $this->costInterface->expects($this->exactly(3))->method('getCost')->willReturn(-15);
+        $this->costInterface->expects($this->exactly(4))->method('getCost')->willReturn(-15);
         $this->validationResult
             ->expects($this->atLeastOnce())
             ->method('getFailedItems');
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/Validation/TierPriceValidatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/Validation/TierPriceValidatorTest.php
index 249a3642024592c67d16eb056a78b7efa41f918e..0505d7c1b8175e6ef476d8846be7743c1a3a1181 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/Validation/TierPriceValidatorTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/Validation/TierPriceValidatorTest.php
@@ -6,14 +6,23 @@
 
 namespace Magento\Catalog\Test\Unit\Model\Product\Price\Validation;
 
-use Magento\Catalog\Api\Data\TierPriceInterface;
-
 /**
- * Class TierPriceValidatorTest.
+ * Test for \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator.
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class TierPriceValidatorTest extends \PHPUnit_Framework_TestCase
 {
+    /**
+     * @var ObjectManagerHelper
+     */
+    private $objectManagerHelper;
+
+    /**
+     * @var \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator
+     */
+    private $tierPriceValidator;
+
     /**
      * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -45,9 +54,9 @@ class TierPriceValidatorTest extends \PHPUnit_Framework_TestCase
     private $tierPricePersistence;
 
     /**
-     * @var \Magento\Catalog\Api\Data\TierPriceInterface|\PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\Catalog\Model\Product\Price\Validation\Result|\PHPUnit_Framework_MockObject_MockObject
      */
-    private $tierPriceInterface;
+    private $validationResult;
 
     /**
      * @var \Magento\Catalog\Model\Product\Price\InvalidSkuChecker|\PHPUnit_Framework_MockObject_MockObject
@@ -55,90 +64,52 @@ class TierPriceValidatorTest extends \PHPUnit_Framework_TestCase
     private $invalidSkuChecker;
 
     /**
-     * @var \Magento\Catalog\Model\Product\Price\Validation\Result|\PHPUnit_Framework_MockObject_MockObject
-     */
-    private $validationResult;
-
-    /**
-     * @var \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator
+     * @var \Magento\Catalog\Api\Data\TierPriceInterface|\PHPUnit_Framework_MockObject_MockObject
      */
-    private $model;
+    private $tierPrice;
 
     /**
-     * Set up.
-     *
-     * @return void
+     * {@inheritdoc}
      */
     protected function setUp()
     {
-        $this->productIdLocator = $this->getMockForAbstractClass(
-            \Magento\Catalog\Model\ProductIdLocatorInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['retrieveProductIdsBySkus']
-        );
-        $this->searchCriteriaBuilder = $this->getMock(
-            \Magento\Framework\Api\SearchCriteriaBuilder::class,
-            ['addFilters', 'create'],
-            [],
-            '',
-            false
-        );
-        $this->filterBuilder = $this->getMock(
-            \Magento\Framework\Api\FilterBuilder::class,
-            ['setField', 'setValue', 'create'],
-            [],
-            '',
-            false
-        );
-        $this->filterBuilder->method('setField')->willReturnSelf();
-        $this->filterBuilder->method('setValue')->willReturnSelf();
-        $this->customerGroupRepository = $this->getMockForAbstractClass(
-            \Magento\Customer\Api\GroupRepositoryInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getList']
-        );
-        $this->websiteRepository = $this->getMockForAbstractClass(
-            \Magento\Store\Api\WebsiteRepositoryInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getById']
-        );
-        $this->tierPricePersistence = $this->getMock(
-            \Magento\Catalog\Model\Product\Price\TierPricePersistence::class,
-            ['addFilters', 'create'],
-            [],
-            '',
-            false
-        );
-        $this->tierPriceInterface = $this->getMockForAbstractClass(
-            \Magento\Catalog\Api\Data\TierPriceInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getSku', 'getPrice', 'getPriceType', 'getQuantity', 'getWebsiteId', 'getCustomerGroup']
-        );
+        $this->productIdLocator = $this->getMockBuilder(\Magento\Catalog\Model\ProductIdLocatorInterface::class)
+            ->setMethods(['retrieveProductIdsBySkus'])
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->searchCriteriaBuilder = $this->getMockBuilder(\Magento\Framework\Api\SearchCriteriaBuilder::class)
+            ->setMethods(['addFilters', 'create'])
+            ->disableOriginalConstructor()->getMock();
+
+        $this->filterBuilder = $this->getMockBuilder(\Magento\Framework\Api\FilterBuilder::class)
+            ->setMethods(['setField', 'setValue', 'create'])
+            ->disableOriginalConstructor()->getMock();
+
+        $this->customerGroupRepository = $this->getMockBuilder(\Magento\Customer\Api\GroupRepositoryInterface::class)
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->websiteRepository = $this->getMockBuilder(\Magento\Store\Api\WebsiteRepositoryInterface::class)
+            ->setMethods(['getById'])
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->tierPricePersistence = $this
+            ->getMockBuilder(\Magento\Catalog\Model\Product\Price\TierPricePersistence::class)
+            ->disableOriginalConstructor()->getMock();
+
         $this->validationResult = $this->getMockBuilder(\Magento\Catalog\Model\Product\Price\Validation\Result::class)
-            ->disableOriginalConstructor()
-            ->getMock();
+            ->setMethods(['addFailedItem'])
+            ->disableOriginalConstructor()->getMock();
+
         $this->invalidSkuChecker = $this->getMockBuilder(\Magento\Catalog\Model\Product\Price\InvalidSkuChecker::class)
-            ->disableOriginalConstructor()
-            ->getMock();
+            ->setMethods(['isSkuListValid', 'retrieveInvalidSkuList'])
+            ->disableOriginalConstructor()->getMock();
+
+        $this->tierPrice = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)
+            ->setMethods(['getSku', 'getPrice', 'getPriceType', 'getQuantity', 'getWebsiteId'])
+            ->disableOriginalConstructor()->getMockForAbstractClass();
 
-        $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-        $this->model = $objectManager->getObject(
+        $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->tierPriceValidator = $this->objectManagerHelper->getObject(
             \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator::class,
             [
                 'productIdLocator' => $this->productIdLocator,
@@ -148,186 +119,182 @@ class TierPriceValidatorTest extends \PHPUnit_Framework_TestCase
                 'websiteRepository' => $this->websiteRepository,
                 'tierPricePersistence' => $this->tierPricePersistence,
                 'validationResult' => $this->validationResult,
-                'invalidSkuChecker' => $this->invalidSkuChecker,
-                'allowedProductTypes' => ['simple', 'virtual', 'bundle', 'downloadable'],
+                'invalidSkuChecker' => $this->invalidSkuChecker
             ]
         );
     }
 
     /**
-     * Test retrieveValidPrices method.
+     * Prepare CustomerGroupRepository mock.
      *
+     * @param array $returned
      * @return void
      */
-    public function testRetrieveValidPrices()
+    private function prepareCustomerGroupRepositoryMock(array $returned)
     {
-        $sku = 'sku_1';
-        $idsBySku = [
-            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
-            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
-        ];
-        $this->productIdLocator->expects($this->once())->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
-        $productPrice = 15;
-        $this->tierPriceInterface->expects($this->exactly(10))->method('getSku')->willReturn($sku);
-        $this->invalidSkuChecker->expects($this->once())->method('retrieveInvalidSkuList')->willReturn([]);
-        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
-        $this->tierPriceInterface
-            ->expects($this->exactly(2))
-            ->method('getPriceType')
-            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
-        $this->tierPriceInterface->expects($this->exactly(3))->method('getQuantity')->willReturn(2);
-        $this->checkWebsite($this->tierPriceInterface);
-        $this->checkGroup($this->tierPriceInterface);
-        $this->model->retrieveValidationResult([$this->tierPriceInterface], []);
+        $searchCriteria = $this
+            ->getMockBuilder(\Magento\Framework\Api\Search\SearchCriteriaInterface::class)
+            ->disableOriginalConstructor()->getMock();
+
+        $filter = $this->getMockBuilder(\Magento\Framework\Api\AbstractSimpleObject::class)
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $this->filterBuilder->expects($this->atLeastOnce())->method('setField')->willReturnSelf();
+        $this->filterBuilder->expects($this->atLeastOnce())->method('setValue')->willReturnSelf();
+        $this->filterBuilder->expects($this->atLeastOnce())->method('create')->willReturn($filter);
+
+        $this->searchCriteriaBuilder->expects($this->atLeastOnce())->method('addFilters')->willReturnSelf();
+        $this->searchCriteriaBuilder->expects($this->atLeastOnce())->method('create')->willReturn($searchCriteria);
+
+        $customerGroupSearchResults = $this
+            ->getMockBuilder(\Magento\Customer\Api\Data\GroupSearchResultsInterface::class)
+            ->disableOriginalConstructor()->getMock();
+        $customerGroupSearchResults->expects($this->once())->method('getItems')
+            ->willReturn($returned['customerGroupSearchResults_getItems']);
+
+        $this->customerGroupRepository->expects($this->atLeastOnce())->method('getList')
+            ->willReturn($customerGroupSearchResults);
     }
 
     /**
-     * Test retrieveValidPrices method with downloadable product.
+     * Prepare retrieveValidationResult().
+     *
+     * @param string $sku
+     * @param array $returned
+     * @return void
      */
-    public function testRetrieveValidPricesWithDownloadableProduct()
+    private function prepareRetrieveValidationResultMethod($sku, array $returned)
     {
+        $this->tierPrice->expects($this->atLeastOnce())->method('getSku')->willReturn($sku);
+        $tierPriceValue = 104;
+        $this->tierPrice->expects($this->atLeastOnce())->method('getPrice')->willReturn($tierPriceValue);
+        $this->tierPrice->expects($this->atLeastOnce())->method('getPriceType')
+            ->willReturn($returned['tierPrice_getPriceType']);
+        $qty = 0;
+        $this->tierPrice->expects($this->atLeastOnce())->method('getQuantity')->willReturn($qty);
+        $websiteId = 0;
+        $invalidWebsiteId = 4;
+        $this->tierPrice->expects($this->atLeastOnce())->method('getWebsiteId')
+            ->willReturnOnConsecutiveCalls($websiteId, $websiteId, $websiteId, $invalidWebsiteId, $websiteId);
+        $this->tierPrice->expects($this->atLeastOnce())->method('getCustomerGroup')
+            ->willReturn($returned['tierPrice_getCustomerGroup']);
+
+        $skuDiff = [$sku];
+        $this->invalidSkuChecker->expects($this->atLeastOnce())->method('retrieveInvalidSkuList')->willReturn($skuDiff);
+
+        $productId = 3346346;
+        $productType = \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE;
         $idsBySku = [
-            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
-            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
+            $sku => [$productId => $productType]
         ];
-        $this->productIdLocator->expects($this->once())->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
-        $this->tierPriceInterface->expects($this->exactly(10))->method('getSku')->willReturn('sku_1');
-        $this->invalidSkuChecker->expects($this->once())->method('retrieveInvalidSkuList')->willReturn([]);
-        $productPrice = 15;
-        $this->tierPriceInterface->expects($this->exactly(2))->method('getPrice')->willReturn($productPrice);
-        $this->tierPriceInterface
-            ->expects($this->exactly(2))
-            ->method('getPriceType')
-            ->willReturn(TierPriceInterface::PRICE_TYPE_FIXED);
-        $this->tierPriceInterface->expects($this->exactly(3))->method('getQuantity')->willReturn(2);
-        $this->checkWebsite($this->tierPriceInterface);
-        $this->checkGroup($this->tierPriceInterface);
-        $this->validationResult
-            ->expects($this->never())
-            ->method('addFailedItem');
-        $this->model->retrieveValidationResult([$this->tierPriceInterface], []);
+        $this->productIdLocator->expects($this->atLeastOnce())->method('retrieveProductIdsBySkus')
+            ->willReturn($idsBySku);
     }
 
     /**
-     * Test method call with invalid values.
+     * Test for validateSkus().
+     *
+     * @return void
      */
-    public function testRetrieveValidPricesWithInvalidCall()
+    public function testValidateSkus()
     {
-        $idsBySku = [
-            'sku_1' => [1 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
-            'sku_2' => [2 => \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL],
-            'invalid' => [3 => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE],
-        ];
+        $skus = ['SDFS234234'];
 
-        $this->tierPriceInterface->expects($this->exactly(10))->method('getSku')->willReturn('sku_1');
-        $this->invalidSkuChecker->expects($this->once())->method('retrieveInvalidSkuList')->willReturn(['invalid']);
-        $this->productIdLocator->expects($this->once())->method('retrieveProductIdsBySkus')->willReturn($idsBySku);
-        $this->validationResult
-            ->expects($this->exactly(5))
-            ->method('addFailedItem');
-        $this->tierPriceInterface->expects($this->exactly(3))->method('getPrice')->willReturn('-90');
-        $this->tierPriceInterface->expects($this->exactly(2))->method('getPriceType')->willReturn('unknown');
-        $this->tierPriceInterface->expects($this->exactly(4))->method('getQuantity')->willReturn('-90');
-        $this->websiteRepository->method('getById')
-            ->willThrowException(new \Magento\Framework\Exception\NoSuchEntityException());
-        $searchCriteria = $this->getMockForAbstractClass(
-            \Magento\Framework\Api\SearchCriteriaInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['create']
-        );
-        $searchCriteria->method('create')->willReturnSelf();
-        $this->searchCriteriaBuilder->method('addFilters')->willReturn($searchCriteria);
-        $this->searchCriteriaBuilder->expects($this->once())->method('addFilters')->willReturnSelf();
-        $this->filterBuilder->expects($this->once())->method('setField')->with('customer_group_code')->willReturnSelf();
-        $this->filterBuilder->expects($this->once())->method('setValue')->willReturnSelf();
-        $searchResults = $this->getMockForAbstractClass(
-            \Magento\Customer\Api\Data\GroupSearchResultsInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getItems']
-        );
-        $this->filterBuilder->expects($this->atLeastOnce())->method('create')->willReturnSelf();
-        $searchResults->expects($this->atLeastOnce())->method('getItems')->willReturn([]);
-        $this->customerGroupRepository
-            ->expects($this->atLeastOnce())
-            ->method('getList')
-            ->willReturn($searchResults);
-        $this->model->retrieveValidationResult([$this->tierPriceInterface], []);
+        $this->invalidSkuChecker->expects($this->atLeastOnce())->method('isSkuListValid');
+
+        $expected = null;
+        $this->assertEquals($expected, $this->tierPriceValidator->validateSkus($skus));
     }
 
     /**
-     * Check website.
+     * Test for retrieveValidationResult().
      *
-     * @param \PHPUnit_Framework_MockObject_MockObject $price
+     * @param array $returned
+     * @dataProvider retrieveValidationResultDataProvider
+     * @return void
      */
-    private function checkWebsite(\PHPUnit_Framework_MockObject_MockObject $price)
+    public function testRetrieveValidationResult(array $returned)
     {
-        $website = $this->getMockForAbstractClass(
-            \Magento\Store\Api\Data\WebsiteInterface::class,
-            [],
-            '',
-            false
-        );
-        $price->expects($this->exactly(3))->method('getWebsiteId')->willReturn(1);
-        $this->websiteRepository->expects($this->once())->method('getById')->willReturn($website);
+        $sku = 'ASDF234234';
+
+        $prices = [$this->tierPrice];
+        $existingPrices = [$this->tierPrice];
+
+        $this->prepareRetrieveValidationResultMethod($sku, $returned);
+
+        $website = $this->getMockBuilder(\Magento\Store\Api\Data\WebsiteInterface::class)
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+        $this->websiteRepository->expects($this->atLeastOnce())->method('getById')->willReturn($website);
+
+        $this->prepareCustomerGroupRepositoryMock($returned);
+
+        $expects = $this->validationResult;
+        $this->assertEquals($expects, $this->tierPriceValidator->retrieveValidationResult($prices, $existingPrices));
     }
 
     /**
-     * Check group.
+     * Data provider for retrieveValidationResult() test.
      *
-     * @param \PHPUnit_Framework_MockObject_MockObject $price
+     * @return array
      */
-    private function checkGroup(\PHPUnit_Framework_MockObject_MockObject $price)
+    public function retrieveValidationResultDataProvider()
     {
-        $searchCriteria = $this->getMock(
-            \Magento\Framework\Api\SearchCriteria::class,
-            [],
-            [],
-            '',
-            false
-        );
-        $searchResults = $this->getMockForAbstractClass(
-            \Magento\Customer\Api\Data\GroupSearchResultsInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getItems']
-        );
-        $group = $this->getMockForAbstractClass(
-            \Magento\Customer\Api\Data\GroupInterface::class,
-            [],
-            '',
-            false,
-            true,
-            true,
-            ['getCode', 'getId']
-        );
+        $customerGroupName = 'test_Group';
+
+        $customerGroup = $this->getMockBuilder(\Magento\Customer\Api\Data\GroupInterface::class)
+            ->setMethods(['getCode', 'getId'])
+            ->disableOriginalConstructor()->getMockForAbstractClass();
+
+        $customerGroup->expects($this->atLeastOnce())->method('getCode')->willReturn($customerGroupName);
+        $customerGroupId = 23;
+        $customerGroup->expects($this->atLeastOnce())->method('getId')->willReturn($customerGroupId);
+
+        return [
+            [
+                [
+                    'tierPrice_getCustomerGroup' => $customerGroupName,
+                    'tierPrice_getPriceType' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT,
+                    'customerGroupSearchResults_getItems' => [$customerGroup]
+                ]
+            ],
+            [
+                [
+                    'tierPrice_getCustomerGroup' => $customerGroupName,
+                    'tierPrice_getPriceType' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_FIXED,
+                    'customerGroupSearchResults_getItems' => []
+                ]
+            ]
+        ];
+    }
+
+    /**
+     * Test for retrieveValidationResult() with Exception.
+     *
+     * @return void
+     */
+    public function testRetrieveValidationResultWithException()
+    {
+        $sku = 'ASDF234234';
+        $customerGroupName = 'test_Group';
+
+        $prices = [$this->tierPrice];
+        $existingPrices = [$this->tierPrice];
+
+        $returned = [
+            'tierPrice_getPriceType' => \Magento\Catalog\Api\Data\TierPriceInterface::PRICE_TYPE_DISCOUNT,
+            'customerGroupSearchResults_getItems' => [],
+            'tierPrice_getCustomerGroup' => $customerGroupName,
+        ];
+
+        $this->prepareRetrieveValidationResultMethod($sku, $returned);
+
+        $exception = new \Magento\Framework\Exception\NoSuchEntityException();
+
+        $this->websiteRepository->expects($this->atLeastOnce())->method('getById')->willThrowException($exception);
+
+        $this->prepareCustomerGroupRepositoryMock($returned);
 
-        $price->expects($this->exactly(3))->method('getCustomerGroup')->willReturn('wholesale');
-        $this->searchCriteriaBuilder->expects($this->once())->method('addFilters')->willReturnSelf();
-        $this->filterBuilder->expects($this->once())->method('setField')->with('customer_group_code')->willReturnSelf();
-        $this->filterBuilder->expects($this->once())->method('setValue')->with('wholesale')->willReturnSelf();
-        $this->filterBuilder->expects($this->once())->method('create')->willReturnSelf();
-        $this->searchCriteriaBuilder
-            ->expects($this->once())
-            ->method('create')
-            ->willReturn($searchCriteria);
-        $this->customerGroupRepository
-            ->expects($this->once())
-            ->method('getList')
-            ->with($searchCriteria)
-            ->willReturn($searchResults);
-        $searchResults->expects($this->once())->method('getItems')->willReturn([$group]);
-        $group->expects($this->once())->method('getCode')->willReturn('wholesale');
-        $group->expects($this->once())->method('getId')->willReturn(4);
+        $expects = $this->validationResult;
+        $this->assertEquals($expects, $this->tierPriceValidator->retrieveValidationResult($prices, $existingPrices));
     }
 }
diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php
index e9ca9c5ca646cb0f2ad106e0b1e084eff479671d..fb988ddde594a7d26cc9f0bfeb7f649397bb60f2 100644
--- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php
+++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php
@@ -38,7 +38,7 @@ class ProductView
         );
 
         $params = [];
-        $params['minAllowed']  = max((float)$stockItem->getQtyMinAllowed(), 1);
+        $params['minAllowed']  = (float)$stockItem->getMinSaleQty();
         if ($stockItem->getQtyMaxAllowed()) {
             $params['maxAllowed'] = $stockItem->getQtyMaxAllowed();
         }
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php
index c0ba42d1981ca2a12f3ea6aa063854ce465461bb..267ff26bb0ccbf7d4e8b84d8a4b09c256c5123d1 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php
@@ -28,7 +28,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase
 
         $this->stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Model\Stock\Item::class)
             ->disableOriginalConstructor()
-            ->setMethods(['getQtyMinAllowed', 'getQtyMaxAllowed', 'getQtyIncrements'])
+            ->setMethods(['getMinSaleQty', 'getQtyMaxAllowed', 'getQtyIncrements'])
             ->getMock();
 
         $this->stockRegistry = $this->getMockBuilder(\Magento\CatalogInventory\Api\StockRegistryInterface::class)
@@ -47,7 +47,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase
         $result = [
             'validate-item-quantity' =>
                 [
-                    'minAllowed' => 2,
+                    'minAllowed' => 0.5,
                     'maxAllowed' => 5,
                     'qtyIncrements' => 3
                 ]
@@ -73,7 +73,7 @@ class ProductViewTest extends \PHPUnit_Framework_TestCase
             ->method('getStockItem')
             ->with('productId', 'websiteId')
             ->willReturn($this->stockItem);
-        $this->stockItem->expects($this->once())->method('getQtyMinAllowed')->willReturn(2);
+        $this->stockItem->expects($this->once())->method('getMinSaleQty')->willReturn(0.5);
         $this->stockItem->expects($this->any())->method('getQtyMaxAllowed')->willReturn(5);
         $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3);
 
diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml
index 31a5dcea3a18f8b41eff7215fbfcdd499d5d4dac..4b486cd346bde1514dccdd27f0e9ac89ed9f8de4 100644
--- a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml
+++ b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml
@@ -179,7 +179,6 @@
                             <item name="dataScope" xsi:type="string">min_sale_qty</item>
                             <item name="validation" xsi:type="array">
                                 <item name="validate-number" xsi:type="boolean">true</item>
-                                <item name="validate-digits" xsi:type="boolean">true</item>
                             </item>
                             <item name="sortOrder" xsi:type="string">0</item>
                             <item name="value" xsi:type="object">Magento\CatalogInventory\Model\Source\StockConfiguration</item>
diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php
index 0e8df9e08f11e82ddf68896b48254fb673eacb1d..5d7cd9e51a862897e445dba02b2ad1d8957cf001 100644
--- a/app/code/Magento/Checkout/Model/Cart.php
+++ b/app/code/Magento/Checkout/Model/Cart.php
@@ -358,11 +358,10 @@ class Cart extends DataObject implements CartInterface
         if ($productId) {
             $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
             $minimumQty = $stockItem->getMinSaleQty();
-            //If product was not found in cart and there is set minimal qty for it
+            //If product quantity is not specified in request and there is set minimal qty for it
             if ($minimumQty
                 && $minimumQty > 0
                 && !$request->getQty()
-                && !$this->getQuote()->hasProductId($productId)
             ) {
                 $request->setQty($minimumQty);
             }
diff --git a/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c758dba4acbde030cc825059ae332f892160ef2
--- /dev/null
+++ b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Paypal\Model\Config\Structure;
+
+/**
+ * PayPal change structure of payment methods configuration in admin panel.
+ */
+class PaymentSectionModifier
+{
+    /**
+     * Identifiers of special payment method configuration groups
+     *
+     * @var array
+     */
+    private static $specialGroups = [
+        'account',
+        'recommended_solutions',
+        'other_paypal_payment_solutions',
+        'other_payment_methods',
+    ];
+
+    /**
+     * Returns changed section structure.
+     *
+     * Payment configuration has predefined special blocks:
+     *  - Account information (id = account),
+     *  - Recommended Solutions (id = recommended_solutions),
+     *  - Other PayPal paymnt solution (id = other_paypal_payment_solutions),
+     *  - Other payment methods (id = other_payment_methods).
+     * All payment methods configuration should be moved to one of this group.
+     * To move payment method to specific configuration group specify "displayIn"
+     * attribute in system.xml file equals to any id of predefined special group.
+     * If "displayIn" attribute is not specified then payment method moved to "Other payment methods" group
+     *
+     * @param array $initialStructure
+     * @return array
+     */
+    public function modify(array $initialStructure)
+    {
+        $changedStructure = array_fill_keys(self::$specialGroups, []);
+
+        foreach ($initialStructure as $childSection => $childData) {
+            if (in_array($childSection, self::$specialGroups)) {
+                if (isset($changedStructure[$childSection]['children'])) {
+                    $children = $changedStructure[$childSection]['children'];
+                    if (isset($childData['children'])) {
+                        $children += $childData['children'];
+                    }
+                    $childData['children'] = $children;
+                    unset($children);
+                }
+                $changedStructure[$childSection] = $childData;
+            } else {
+                $moveInstructions = $this->getMoveInstructions($childSection, $childData);
+                if (!empty($moveInstructions)) {
+                    foreach ($moveInstructions as $moveInstruction) {
+                        unset($childData['children'][$moveInstruction['section']]);
+                        unset($moveInstruction['data']['displayIn']);
+                        $changedStructure
+                            [$moveInstruction['parent']]
+                                ['children']
+                                    [$moveInstruction['section']] = $moveInstruction['data'];
+                    }
+                }
+                if (!isset($moveInstructions[$childSection])) {
+                    $changedStructure['other_payment_methods']['children'][$childSection] = $childData;
+                }
+            }
+        }
+
+        return $changedStructure;
+    }
+
+    /**
+     * Recursively collect groups that should be moved to special section
+     *
+     * @param string $section
+     * @param array $data
+     * @return array
+     */
+    private function getMoveInstructions($section, $data)
+    {
+        $moved = [];
+
+        if (array_key_exists('children', $data)) {
+            foreach ($data['children'] as $childSection => $childData) {
+                $movedChildren = $this->getMoveInstructions($childSection, $childData);
+                if (isset($movedChildren[$childSection])) {
+                    unset($data['children'][$childSection]);
+                }
+                $moved = array_merge($moved, $movedChildren);
+            }
+        }
+
+        if (isset($data['displayIn']) && in_array($data['displayIn'], self::$specialGroups)) {
+            $moved = array_merge(
+                [
+                    $section => [
+                    'parent' => $data['displayIn'],
+                    'section' => $section,
+                    'data' => $data
+                    ]
+                ],
+                $moved
+            );
+        }
+
+        return $moved;
+    }
+}
diff --git a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php
index b026aa09692930fea7a58c1afc2946b280bad9fa..0d07abfb8047fc1c94bd9aba04cb15a0c6fdabfa 100644
--- a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php
+++ b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php
@@ -10,6 +10,8 @@ use Magento\Config\Model\Config\Structure;
 use Magento\Config\Model\Config\Structure\Element\Section;
 use Magento\Config\Model\Config\Structure\ElementInterface;
 use Magento\Paypal\Helper\Backend as BackendHelper;
+use Magento\Framework\App\ObjectManager;
+use Magento\Paypal\Model\Config\Structure\PaymentSectionModifier;
 
 /**
  * Plugin for \Magento\Config\Model\Config\Structure
@@ -31,6 +33,11 @@ class StructurePlugin
      */
     private $scopeDefiner;
 
+    /**
+     * @var PaymentSectionModifier
+     */
+    private $paymentSectionModifier;
+
     /**
      * @var string[]
      */
@@ -50,12 +57,18 @@ class StructurePlugin
 
     /**
      * @param ScopeDefiner $scopeDefiner
-     * @param BackendHelper $helper
+     * @param BackendHelper $backendHelper
+     * @param PaymentSectionModifier|null $paymentSectionModifier
      */
-    public function __construct(ScopeDefiner $scopeDefiner, BackendHelper $helper)
-    {
+    public function __construct(
+        ScopeDefiner $scopeDefiner,
+        BackendHelper $backendHelper,
+        PaymentSectionModifier $paymentSectionModifier = null
+    ) {
         $this->scopeDefiner = $scopeDefiner;
-        $this->backendHelper = $helper;
+        $this->backendHelper = $backendHelper;
+        $this->paymentSectionModifier = $paymentSectionModifier
+                                      ?: ObjectManager::getInstance()->get(PaymentSectionModifier::class);
     }
 
     /**
@@ -118,62 +131,17 @@ class StructurePlugin
     }
 
     /**
-     * Change payment config structure
-     *
-     * Groups which have `displayIn` element, transfer to appropriate group.
-     * Groups without `displayIn` transfer to other payment methods group.
+     * Changes payment config structure.
      *
      * @param Section $result
      * @return void
      */
     private function restructurePayments(Section $result)
     {
-        $sectionMap = [
-            'account' => [],
-            'recommended_solutions' => [],
-            'other_paypal_payment_solutions' => [],
-            'other_payment_methods' => []
-        ];
-
-        $configuration = $result->getData();
-
-        foreach ($configuration['children'] as $section => $data) {
-            if (array_key_exists($section, $sectionMap)) {
-                $sectionMap[$section] = $data;
-            } elseif ($displayIn = $this->getDisplayInSection($section, $data)) {
-                $sectionMap[$displayIn['parent']]['children'][$displayIn['section']] = $displayIn['data'];
-            } else {
-                $sectionMap['other_payment_methods']['children'][$section] = $data;
-            }
-        }
-
-        $configuration['children'] = $sectionMap;
-        $result->setData($configuration, $this->scopeDefiner->getScope());
-    }
-
-    /**
-     * Recursive search of `displayIn` element in node children
-     *
-     * @param string $section
-     * @param array $data
-     * @return array|null
-     */
-    private function getDisplayInSection($section, $data)
-    {
-        if (is_array($data) && array_key_exists('displayIn', $data)) {
-            return [
-                'parent' => $data['displayIn'],
-                'section' => $section,
-                'data' => $data
-            ];
-        }
-
-        if (array_key_exists('children', $data)) {
-            foreach ($data['children'] as $childSection => $childData) {
-                return $this->getDisplayInSection($childSection, $childData);
-            }
-        }
-
-        return null;
+        $sectionData = $result->getData();
+        $sectionInitialStructure = isset($sectionData['children']) ? $sectionData['children'] : [];
+        $sectionChangedStructure = $this->paymentSectionModifier->modify($sectionInitialStructure);
+        $sectionData['children'] = $sectionChangedStructure;
+        $result->setData($sectionData, $this->scopeDefiner->getScope());
     }
 }
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fdea2375d8497b76e573d5b8fe610e8adc14efcd
--- /dev/null
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/PaymentSectionModifierTest.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Paypal\Test\Unit\Model\Config\Structure;
+
+use Magento\Paypal\Model\Config\Structure\PaymentSectionModifier;
+
+class PaymentSectionModifierTest extends \PHPUnit_Framework_TestCase
+{
+    private static $specialGroups = [
+        'account',
+        'recommended_solutions',
+        'other_paypal_payment_solutions',
+        'other_payment_methods',
+    ];
+
+    /**
+     * @param string $case
+     * @param array $structure
+     * @dataProvider caseProvider
+     */
+    public function testSpecialGroupsPresent($case, $structure)
+    {
+        $modifier = new PaymentSectionModifier();
+        $modifiedStructure = $modifier->modify($structure);
+        $presentSpecialGroups = array_intersect(
+            self::$specialGroups,
+            array_keys($modifiedStructure)
+        );
+
+        $this->assertEquals(
+            self::$specialGroups,
+            $presentSpecialGroups,
+            sprintf('All special groups must be present in %s case', $case)
+        );
+    }
+
+    /**
+     * @param string $case
+     * @param array $structure
+     * @dataProvider caseProvider
+     */
+    public function testOnlySpecialGroupsPresent($case, $structure)
+    {
+        $modifier = new PaymentSectionModifier();
+        $modifiedStructure = $modifier->modify($structure);
+        $presentNotSpecialGroups = array_diff(
+            array_keys($modifiedStructure),
+            self::$specialGroups
+        );
+
+        $this->assertEquals(
+            [],
+            $presentNotSpecialGroups,
+            sprintf('Only special groups should be present at top level in "%s" case', $case)
+        );
+    }
+
+    /**
+     * @param string $case
+     * @param array $structure
+     * @dataProvider caseProvider
+     */
+    public function testGroupsNotRemovedAfterModification($case, $structure)
+    {
+        $modifier = new PaymentSectionModifier();
+        $modifiedStructure = $modifier->modify($structure);
+
+        $removedGroups = array_diff(
+            $this->fetchAllAvailableGroups($structure),
+            $this->fetchAllAvailableGroups($modifiedStructure)
+        );
+
+        $this->assertEquals(
+            [],
+            $removedGroups,
+            sprintf('Groups should not be removed after modification in "%s" case', $case)
+        );
+    }
+
+    public function testMovedToTargetSpecialGroup()
+    {
+        $structure = [
+            'some_payment_method1' => [
+                'id' => 'some_payment_method1',
+                'displayIn' => 'recommended_solutions',
+            ],
+            'some_group' => [
+                'id' => 'some_group',
+                'children' => [
+                    'some_payment_method2' => [
+                        'id' => 'some_payment_method2',
+                        'displayIn' => 'recommended_solutions'
+                    ],
+                    'some_payment_method3' => [
+                        'id' => 'some_payment_method3',
+                        'displayIn' => 'other_payment_methods'
+                    ],
+                    'some_payment_method4' => [
+                        'id' => 'some_payment_method4',
+                        'displayIn' => 'recommended_solutions'
+                    ],
+                    'some_payment_method5' => [
+                        'id' => 'some_payment_method5',
+                    ],
+                ]
+            ],
+        ];
+
+        $modifier = new PaymentSectionModifier();
+        $modifiedStructure = $modifier->modify($structure);
+
+        $this->assertEquals(
+            [
+                'account' => [],
+                'recommended_solutions' => [
+                    'children' => [
+                        'some_payment_method1' => [
+                            'id' => 'some_payment_method1',
+                        ],
+                        'some_payment_method2' => [
+                            'id' => 'some_payment_method2',
+                        ],
+                        'some_payment_method4' => [
+                            'id' => 'some_payment_method4',
+                        ],
+                    ],
+                ],
+                'other_paypal_payment_solutions' => [],
+                'other_payment_methods' => [
+                    'children' => [
+                        'some_payment_method3' => [
+                            'id' => 'some_payment_method3',
+                        ],
+                        'some_group' => [
+                            'id' => 'some_group',
+                            'children' => [
+                                'some_payment_method5' => [
+                                    'id' => 'some_payment_method5',
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            $modifiedStructure,
+            'Some group is not moved correctly'
+        );
+    }
+
+    /**
+     * This helper method walks recursively through configuration structure and
+     * collect available configuration groups
+     *
+     * @param array $structure
+     * @return array Sorted list of group identifiers
+     */
+    private function fetchAllAvailableGroups($structure)
+    {
+        $availableGroups = [];
+        foreach ($structure as $group => $data) {
+            $availableGroups[] = $group;
+            if (isset($data['children'])) {
+                $availableGroups = array_merge(
+                    $availableGroups,
+                    $this->fetchAllAvailableGroups($data['children'])
+                );
+            }
+        }
+        $availableGroups = array_values(array_unique($availableGroups));
+        sort($availableGroups);
+        return $availableGroups;
+    }
+
+    public function caseProvider()
+    {
+        return include __DIR__ . '/_files/payment_section_structure_variations.php';
+    }
+}
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php
new file mode 100644
index 0000000000000000000000000000000000000000..3dc323a1b2207c0253b6c885ae4e406f57bfc87f
--- /dev/null
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/_files/payment_section_structure_variations.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+return [
+    [
+        'empty structure',
+        []
+    ],
+    [
+        'structure with special groups at the begin of the list',
+        [
+            'account' => [
+                'id' => 'account',
+            ],
+            'recommended_solutions' => [
+                'id' => 'recommended_solutions',
+            ],
+            'other_paypal_payment_solutions' => [
+                'id' => 'other_paypal_payment_solutions',
+            ],
+            'other_payment_methods' => [
+                'id' => 'other_payment_methods',
+            ],
+            'some_payment_method' => [
+                'id' => 'some_payment_method',
+            ],
+        ]
+    ],
+    [
+        'structure with special groups at the end of the list',
+        [
+            'some_payment_method' => [
+                'id' => 'some_payment_method',
+            ],
+            'account' => [
+                'id' => 'account',
+            ],
+            'recommended_solutions' => [
+                'id' => 'recommended_solutions',
+            ],
+            'other_paypal_payment_solutions' => [
+                'id' => 'other_paypal_payment_solutions',
+            ],
+            'other_payment_methods' => [
+                'id' => 'other_payment_methods',
+            ],
+        ]
+    ],
+    [
+        'structure with special groups in the middle of the list',
+        [
+            'some_payment_methodq' => [
+                'id' => 'some_payment_methodq',
+            ],
+            'account' => [
+                'id' => 'account',
+            ],
+            'recommended_solutions' => [
+                'id' => 'recommended_solutions',
+            ],
+            'other_paypal_payment_solutions' => [
+                'id' => 'other_paypal_payment_solutions',
+            ],
+            'other_payment_methods' => [
+                'id' => 'other_payment_methods',
+            ],
+            'some_payment_method2' => [
+                'id' => 'some_payment_method2',
+            ],
+        ]
+    ],
+    [
+        'structure with all assigned groups',
+        [
+            'some_payment_method1' => [
+                'id' => 'some_payment_method1',
+                'displayIn' => 'other_paypal_payment_solutions',
+            ],
+            'some_payment_method2' => [
+                'id' => 'some_payment_method2',
+                'displayIn' => 'recommended_solutions',
+            ],
+        ]
+    ],
+    [
+        'structure with not assigned groups',
+        [
+            'some_payment_method1' => [
+                'id' => 'some_payment_method1',
+                'displayIn' => 'other_paypal_payment_solutions',
+            ],
+            'some_payment_method2' => [
+                'id' => 'some_payment_method2',
+            ],
+        ]
+    ],
+    [
+        'special groups has predefined children',
+        [
+            'recommended_solutions' => [
+                'id' => 'recommended_solutions',
+                'children' => [
+                    'some_payment_method1' => [
+                        'id' => 'some_payment_method1',
+                    ],
+                ]
+            ],
+            'some_payment_method2' => [
+                'id' => 'some_payment_method2',
+                'displayIn' => 'recommended_solutions',
+            ],
+        ]
+    ],
+    [
+        'structure with displayIn that do not reference to special groups',
+        [
+            'some_payment_method1' => [
+                'id' => 'some_payment_method1',
+            ],
+            'some_payment_method2' => [
+                'id' => 'some_payment_method2',
+                'displayIn' => 'some_payment_method1',
+            ],
+        ]
+    ],
+];
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php
index 26dd4af0220aaeebfb10b397a9fa7c494fa36936..2e4d146ac6159b5bf995dca335ea3abe4a06549e 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php
@@ -61,7 +61,10 @@ class StructurePluginTest extends \PHPUnit_Framework_TestCase
         $this->objectManagerHelper = new ObjectManagerHelper($this);
         $this->plugin = $this->objectManagerHelper->getObject(
             ConfigStructurePlugin::class,
-            ['scopeDefiner' => $this->configScopeDefinerMock, 'helper' => $this->backendHelperMock]
+            [
+                'scopeDefiner' => $this->configScopeDefinerMock,
+                'backendHelper' => $this->backendHelperMock
+            ]
         );
     }
 
diff --git a/app/code/Magento/Sales/Setup/InstallSchema.php b/app/code/Magento/Sales/Setup/InstallSchema.php
index 64240feef0f5f4036bed21ce22e14d6f6db57d10..6b0b27739ca15d966ab4cd8259af6b213a939cca 100644
--- a/app/code/Magento/Sales/Setup/InstallSchema.php
+++ b/app/code/Magento/Sales/Setup/InstallSchema.php
@@ -2091,7 +2091,7 @@ class InstallSchema implements InstallSchemaInterface
         )->addColumn(
             'cc_number_enc',
             \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
-            32,
+            128,
             [],
             'Cc Number Enc'
         )->addColumn(
diff --git a/app/code/Magento/Sales/Setup/UpgradeSchema.php b/app/code/Magento/Sales/Setup/UpgradeSchema.php
index 60f93fc765079760b2dd4ca434990337aaee748d..700da396b930d8312dfaaa6015268fa9531ae82b 100644
--- a/app/code/Magento/Sales/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Sales/Setup/UpgradeSchema.php
@@ -84,6 +84,17 @@ class UpgradeSchema implements UpgradeSchemaInterface
                 );
             }
         }
+        if (version_compare($context->getVersion(), '2.0.5', '<')) {
+            $connection = $installer->getConnection(self::$connectionName);
+            $connection->modifyColumn(
+                $installer->getTable('sales_order_payment', self::$connectionName),
+                'cc_number_enc',
+                [
+                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+                    'length' => 128
+                ]
+            );
+        }
     }
 
     /**
diff --git a/app/code/Magento/Shipping/Model/Shipping.php b/app/code/Magento/Shipping/Model/Shipping.php
index 3df54577107a9b4dc512f33df197f83abccdc495..d67ab2ddf8d49d0dd07d933ae213378819c5d4f4 100644
--- a/app/code/Magento/Shipping/Model/Shipping.php
+++ b/app/code/Magento/Shipping/Model/Shipping.php
@@ -5,8 +5,10 @@
  */
 namespace Magento\Shipping\Model;
 
-use Magento\Sales\Model\Order\Shipment;
+use Magento\Framework\App\ObjectManager;
 use Magento\Quote\Model\Quote\Address\RateCollectorInterface;
+use Magento\Quote\Model\Quote\Address\RateRequestFactory;
+use Magento\Sales\Model\Order\Shipment;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -81,6 +83,11 @@ class Shipping implements RateCollectorInterface
      */
     protected $stockRegistry;
 
+    /**
+     * @var RateRequestFactory
+     */
+    private $rateRequestFactory;
+
     /**
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param \Magento\Shipping\Model\Config $shippingConfig
@@ -91,6 +98,9 @@ class Shipping implements RateCollectorInterface
      * @param \Magento\Directory\Model\RegionFactory $regionFactory
      * @param \Magento\Framework\Math\Division $mathDivision
      * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
+     * @param RateRequestFactory $rateRequestFactory
+     *
+     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
@@ -101,7 +111,8 @@ class Shipping implements RateCollectorInterface
         \Magento\Shipping\Model\Shipment\RequestFactory $shipmentRequestFactory,
         \Magento\Directory\Model\RegionFactory $regionFactory,
         \Magento\Framework\Math\Division $mathDivision,
-        \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
+        \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
+        RateRequestFactory $rateRequestFactory = null
     ) {
         $this->_scopeConfig = $scopeConfig;
         $this->_shippingConfig = $shippingConfig;
@@ -112,6 +123,7 @@ class Shipping implements RateCollectorInterface
         $this->_regionFactory = $regionFactory;
         $this->mathDivision = $mathDivision;
         $this->stockRegistry = $stockRegistry;
+        $this->rateRequestFactory = $rateRequestFactory ?: ObjectManager::getInstance()->get(RateRequestFactory::class);
     }
 
     /**
@@ -463,7 +475,7 @@ class Shipping implements RateCollectorInterface
     public function collectRatesByAddress(\Magento\Framework\DataObject $address, $limitCarrier = null)
     {
         /** @var $request \Magento\Quote\Model\Quote\Address\RateRequest */
-        $request = $this->_shipmentRequestFactory->create();
+        $request = $this->rateRequestFactory->create();
         $request->setAllItems($address->getAllItems());
         $request->setDestCountryId($address->getCountryId());
         $request->setDestRegionId($address->getRegionId());
@@ -473,10 +485,13 @@ class Shipping implements RateCollectorInterface
         $request->setPackageWeight($address->getWeight());
         $request->setFreeMethodWeight($address->getFreeMethodWeight());
         $request->setPackageQty($address->getItemQty());
-        $request->setStoreId($this->_storeManager->getStore()->getId());
-        $request->setWebsiteId($this->_storeManager->getStore()->getWebsiteId());
-        $request->setBaseCurrency($this->_storeManager->getStore()->getBaseCurrency());
-        $request->setPackageCurrency($this->_storeManager->getStore()->getCurrentCurrency());
+
+        /** @var \Magento\Store\Api\Data\StoreInterface $store */
+        $store = $this->_storeManager->getStore();
+        $request->setStoreId($store->getId());
+        $request->setWebsiteId($store->getWebsiteId());
+        $request->setBaseCurrency($store->getBaseCurrency());
+        $request->setPackageCurrency($store->getCurrentCurrency());
         $request->setLimitCarrier($limitCarrier);
 
         $request->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax());
diff --git a/app/code/Magento/Vault/Model/PaymentTokenRepository.php b/app/code/Magento/Vault/Model/PaymentTokenRepository.php
index f32e7dbcb45dfe9c6b392504d5c11ffde8f0a460..f904fed1b8ad90168eca6992ca1e03e10b330b67 100644
--- a/app/code/Magento/Vault/Model/PaymentTokenRepository.php
+++ b/app/code/Magento/Vault/Model/PaymentTokenRepository.php
@@ -129,6 +129,7 @@ class PaymentTokenRepository implements PaymentTokenRepositoryInterface
         }
 
         $tokenModel->setIsActive(false);
+        $tokenModel->setIsVisible(false);
         $tokenModel->save();
 
         return true;
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php
index 3da02007eb5082fa8d056486670a8ec077554645..73500ff5ae24cfa395ffb2c10461a53737217ce2 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/BasePriceStorageTest.php
@@ -180,8 +180,12 @@ class BasePriceStorageTest extends WebapiAbstract
                 ]
             ],
             2 => [
-                'message' => 'Requested store is not found.',
-                'parameters' => []
+                'message' =>
+                    'Requested store is not found. Row ID: SKU = not_existing_sku, Store ID: 9999.',
+                'parameters' => [
+                    'not_existing_sku',
+                    '9999'
+                ]
             ]
         ];
 
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php
index ff6a4f5283ff2a5f23d48da8f813df24342cc76f..f04097a17a0762c4f47ae1b1ebded3e512028e75 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CostStorageTest.php
@@ -174,15 +174,19 @@ class CostStorageTest extends WebapiAbstract
                 ]
             ],
             1 => [
-                'message' => 'Invalid attribute %fieldName = %fieldValue.',
+                'message' => 'Invalid attribute Cost = -9999. Row ID: SKU = not_existing_sku, Store ID: 9999.',
                 'parameters' => [
-                    'Cost',
                     '-9999',
+                    'not_existing_sku',
+                    '9999'
                 ]
             ],
             2 => [
-                'message' => 'Requested store is not found.',
-                'parameters' => []
+                'message' => 'Requested store is not found. Row ID: SKU = not_existing_sku, Store ID: 9999.',
+                'parameters' => [
+                    'not_existing_sku',
+                    '9999'
+                ]
             ]
         ];
 
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php
index 054c0ce20cd813c22b73377884e2b51d2ae83e94..f6e325a0c47900ee280b2272b0c2c84edd96ebf9 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php
@@ -17,7 +17,7 @@ class AssertCancelSuccessMessageInShoppingCart extends AbstractConstraint
     /**
      * Cancel success message text.
      */
-    const SUCCESS_MESSAGE = 'Payment was canceled.';
+    const SUCCESS_MESSAGE = 'Your purchase process has been cancelled.';
 
     /**
      * Assert that success message about canceled order is present and correct.
diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php
index 52376ad81245ced6b87694ebbf8d4dd3c70e3a6e..76de7a2ab57d80f751f6c301f12a48dd5393a645 100644
--- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php
+++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Model/ResourceModel/Key/ChangeTest.php
@@ -79,6 +79,7 @@ class ChangeTest extends \PHPUnit_Framework_TestCase
             )
         );
         $this->assertNotContains($testValue, $values1);
+        $this->assertRegExp('/([0-9]+:)([0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+)/', current($values1));
 
         // Verify that the credit card number has been encrypted
         $values2 = $connection->fetchPairs(
@@ -88,6 +89,7 @@ class ChangeTest extends \PHPUnit_Framework_TestCase
             )
         );
         $this->assertNotContains('1111111111', $values2);
+        $this->assertRegExp('/([0-9]+:)([0-9]+:)([a-zA-Z0-9]+:)([a-zA-Z0-9]+)/', current($values1));
 
         /** clean up */
         $select = $connection->select()->from($configModel->getMainTable())->where('path=?', $testPath);
diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9aadc478f00c4b03f534ef12e71ae1538e81c9c8
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Shipping/Model/ShippingTest.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Shipping\Model;
+
+use Magento\Framework\DataObject;
+use Magento\Framework\ObjectManagerInterface;
+use Magento\Quote\Model\Quote\Address\RateResult\Method;
+use Magento\Shipping\Model\Rate\Result;
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * Contains list of tests for Shipping model
+ */
+class ShippingTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var Shipping
+     */
+    private $model;
+
+    /**
+     * @var ObjectManagerInterface
+     */
+    private $objectManager;
+
+    /**
+     * @inheritdoc
+     */
+    protected function setUp()
+    {
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->model = $this->objectManager->get(Shipping::class);
+    }
+
+    /**
+     * Checks shipping rates processing by address.
+     * @covers \Magento\Shipping\Model\Shipping::collectRatesByAddress
+     * @return Result
+     */
+    public function testCollectRatesByAddress()
+    {
+        $address = $this->objectManager->create(DataObject::class, [
+            'data' => [
+                'region_id' => 'CA',
+                'postcode' => '11111',
+                'lastname' => 'John',
+                'firstname' => 'Doe',
+                'street' => 'Some street',
+                'city' => 'Los Angeles',
+                'email' => 'john.doe@example.com',
+                'telephone' => '11111111',
+                'country_id' => 'US',
+                'item_qty' => 1
+            ]
+        ]);
+        /** @var Shipping $result */
+        $result = $this->model->collectRatesByAddress($address, 'flatrate');
+        static::assertInstanceOf(Shipping::class, $result);
+
+        return $result->getResult();
+    }
+
+    /**
+     * Checks shipping rate details for processed address.
+     * @covers \Magento\Shipping\Model\Shipping::collectRatesByAddress
+     * @param Result $result
+     * @depends testCollectRatesByAddress
+     * @magentoConfigFixture carriers/flatrate/active 1
+     * @magentoConfigFixture carriers/flatrate/price 5.00
+     */
+    public function testCollectRates(Result $result)
+    {
+        $rates = $result->getAllRates();
+        static::assertNotEmpty($rates);
+
+        /** @var Method $rate */
+        $rate = array_pop($rates);
+
+        static::assertInstanceOf(Method::class, $rate);
+        static::assertEquals('flatrate', $rate->getData('carrier'));
+        static::assertEquals(5, $rate->getData('price'));
+    }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php
index c22ac69db338392544ad2cada1b908c0bc42aa77..255b660de37edde2ac98cb9ddd1d0f939b8d08f3 100644
--- a/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Vault/Model/PaymentTokenRepositoryTest.php
@@ -8,39 +8,48 @@ namespace Magento\Vault\Model;
 use Magento\Framework\Api\FilterBuilder;
 use Magento\Framework\Api\SearchCriteriaBuilder;
 use Magento\Framework\Api\SortOrderBuilder;
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\TestFramework\ObjectManager;
 
 /**
- * Class PaymentTokenRepositoryTest
- * @package Magento\Vault\Model
+ * PaymentTokenRepositoryTest contains tests for Vault token repository
+ *
  * @magentoDbIsolation enabled
  */
 class PaymentTokenRepositoryTest extends \PHPUnit_Framework_TestCase
 {
-    /** @var  PaymentTokenRepository */
+    /**
+     * @var PaymentTokenRepository
+     */
     private $repository;
 
-    /** @var  SortOrderBuilder */
+    /**
+     * @var SortOrderBuilder
+     */
     private $sortOrderBuilder;
 
-    /** @var FilterBuilder */
+    /**
+     * @var FilterBuilder
+     */
     private $filterBuilder;
 
-    /** @var SearchCriteriaBuilder */
+    /**
+     * @var SearchCriteriaBuilder
+     */
     private $searchCriteriaBuilder;
 
+    /**
+     * @var ObjectManager
+     */
+    private $objectManager;
+
     public function setUp()
     {
-        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
-        $this->repository = $objectManager->create(PaymentTokenRepository::class);
-        $this->searchCriteriaBuilder = $objectManager->create(
-            \Magento\Framework\Api\SearchCriteriaBuilder::class
-        );
-        $this->filterBuilder = $objectManager->get(
-            \Magento\Framework\Api\FilterBuilder::class
-        );
-        $this->sortOrderBuilder = $objectManager->get(
-            \Magento\Framework\Api\SortOrderBuilder::class
-        );
+        $this->objectManager = Bootstrap::getObjectManager();
+        $this->repository = $this->objectManager->create(PaymentTokenRepository::class);
+        $this->searchCriteriaBuilder = $this->objectManager->create(SearchCriteriaBuilder::class);
+        $this->filterBuilder = $this->objectManager->get(FilterBuilder::class);
+        $this->sortOrderBuilder = $this->objectManager->get(SortOrderBuilder::class);
     }
 
     /**
@@ -77,4 +86,26 @@ class PaymentTokenRepositoryTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals('second', array_shift($items)->getPaymentMethodCode());
         $this->assertEquals('first', array_shift($items)->getPaymentMethodCode());
     }
+
+    /**
+     * @covers \Magento\Vault\Model\PaymentTokenRepository::delete
+     * @magentoDataFixture Magento/Vault/_files/token.php
+     */
+    public function testDelete()
+    {
+        /** @var PaymentTokenManagement $tokenManagement */
+        $tokenManagement = $this->objectManager->get(PaymentTokenManagement::class);
+
+        $token = $tokenManagement->getByPublicHash('public_hash', 0);
+
+        /** @var PaymentTokenRepository $tokenRepository */
+        $tokenRepository = $this->objectManager->get(PaymentTokenRepository::class);
+        $tokenRepository->delete($token);
+
+        $deletedToken = $tokenRepository->getById($token->getEntityId());
+
+        static::assertEquals('public_hash', $deletedToken->getPublicHash());
+        static::assertFalse($deletedToken->getIsActive());
+        static::assertFalse($deletedToken->getIsVisible());
+    }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Vault/_files/token.php b/dev/tests/integration/testsuite/Magento/Vault/_files/token.php
new file mode 100644
index 0000000000000000000000000000000000000000..29e8415c4207213f81e4a70914b53844bd724490
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Vault/_files/token.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright © 2013-2017 Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+use Magento\TestFramework\Helper\Bootstrap;
+use Magento\Vault\Model\PaymentToken;
+use Magento\Vault\Model\PaymentTokenRepository;
+
+$objectManager = Bootstrap::getObjectManager();
+
+/** @var PaymentToken $token */
+$token = $objectManager->create(PaymentToken::class);
+
+$token->setGatewayToken('gateway_token')
+    ->setPublicHash('public_hash')
+    ->setPaymentMethodCode('vault_payment')
+    ->setType('card')
+    ->setExpiresAt(strtotime('+1 year'))
+    ->setIsVisible(true)
+    ->setIsActive(true);
+
+/** @var PaymentTokenRepository $tokenRepository */
+$tokenRepository = $objectManager->create(PaymentTokenRepository::class);
+$tokenRepository->save($token);