diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Longtext.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Longtext.php
index e26e1702642285b07e44b08c2177dc1c12cd840c..626c899428ce7b4eac47a221840101adc8aa7319 100644
--- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Longtext.php
+++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Longtext.php
@@ -30,7 +30,7 @@ class Longtext extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstra
             $truncateLength = $this->getColumn()->getTruncate();
         }
         $text = $this->filterManager->truncate(parent::_getValue($row), ['length' => $truncateLength]);
-        if ($this->getColumn()->getEscape()) {
+        if (!$this->getColumn()->hasEscape() || $this->getColumn()->getEscape()) {
             $text = $this->escapeHtml($text);
         }
         if ($this->getColumn()->getNl2br()) {
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Attribute.php
index 0d0037acb67ee870de9c2c3380ce7166e88f9383..d94c3122b89eb362b1eb8ded2867cb3e2772d882 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Attribute.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Attribute.php
@@ -113,27 +113,20 @@ class Attribute extends \Magento\Eav\Model\ResourceModel\Entity\Attribute
     /**
      * Delete entity
      *
-     * @param \Magento\Framework\Model\AbstractModel $object
+     * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object
      * @return $this
      * @throws \Magento\Framework\Exception\LocalizedException
      */
-    public function deleteEntity(\Magento\Framework\Model\AbstractModel $object)
+    public function deleteEntity(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object)
     {
         if (!$object->getEntityAttributeId()) {
             return $this;
         }
 
-        $select = $this->getConnection()->select()->from(
-            $this->getTable('eav_entity_attribute')
-        )->where(
-            'entity_attribute_id = ?',
-            (int)$object->getEntityAttributeId()
-        );
-        $result = $this->getConnection()->fetchRow($select);
-
+        $result = $this->getEntityAttribute($object->getEntityAttributeId());
         if ($result) {
             $attribute = $this->_eavConfig->getAttribute(
-                \Magento\Catalog\Model\Product::ENTITY,
+                $object->getEntityTypeId(),
                 $result['attribute_id']
             );
 
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/Tree.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/Tree.php
index 9d4cb16f18ceae3149e1f3cf69bd6d4e8595f64a..02abcbd944e6245a080934abff9aad569c1ec968 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Category/Tree.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/Tree.php
@@ -5,13 +5,14 @@
  */
 namespace Magento\Catalog\Model\ResourceModel\Category;
 
+use Magento\Framework\Data\Tree\Dbp;
 use Magento\Catalog\Api\Data\CategoryInterface;
 use Magento\Framework\Model\Entity\MetadataPool;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Tree extends \Magento\Framework\Data\Tree\Dbp
+class Tree extends Dbp
 {
     const ID_FIELD = 'id';
 
@@ -124,10 +125,10 @@ class Tree extends \Magento\Framework\Data\Tree\Dbp
             $resource->getConnection('catalog'),
             $resource->getTableName('catalog_category_entity'),
             [
-                \Magento\Framework\Data\Tree\Dbp::ID_FIELD => 'entity_id',
-                \Magento\Framework\Data\Tree\Dbp::PATH_FIELD => 'path',
-                \Magento\Framework\Data\Tree\Dbp::ORDER_FIELD => 'position',
-                \Magento\Framework\Data\Tree\Dbp::LEVEL_FIELD => 'level'
+                Dbp::ID_FIELD => 'entity_id',
+                Dbp::PATH_FIELD => 'path',
+                Dbp::ORDER_FIELD => 'position',
+                Dbp::LEVEL_FIELD => 'level'
             ]
         );
         $this->_eventManager = $eventManager;
diff --git a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php b/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php
index a7e78014789d5b398b6bfc9095461724aa2d598f..8dab4df1c131c162aa953d67de3453e1f24b313a 100644
--- a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php
+++ b/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php
@@ -5,8 +5,14 @@
  */
 namespace Magento\Catalog\Observer;
 
+use Magento\Catalog\Model\Category;
+use Magento\Framework\Data\Collection;
+use Magento\Framework\Data\Tree\Node;
 use Magento\Framework\Event\ObserverInterface;
 
+/**
+ * Observer that add Categories Tree to Topmenu
+ */
 class AddCatalogToTopmenuItemsObserver implements ObserverInterface
 {
     /**
@@ -17,28 +23,38 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
     protected $catalogCategory;
 
     /**
-     * @var \Magento\Catalog\Model\Indexer\Category\Flat\State
+     * @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory
+     */
+    private $collectionFactory;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
      */
-    protected $categoryFlatState;
+    private $storeManager;
 
     /**
-     * @var MenuCategoryData
+     * @var \Magento\Catalog\Model\Layer\Resolver
      */
-    protected $menuCategoryData;
+    private $layerResolver;
 
     /**
      * @param \Magento\Catalog\Helper\Category $catalogCategory
      * @param \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState
-     * @param \Magento\Catalog\Observer\MenuCategoryData $menuCategoryData
+     * @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Catalog\Helper\Category $catalogCategory
+     * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver
      */
     public function __construct(
         \Magento\Catalog\Helper\Category $catalogCategory,
-        \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState,
-        \Magento\Catalog\Observer\MenuCategoryData $menuCategoryData
+        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Catalog\Model\Layer\Resolver $layerResolver
     ) {
         $this->catalogCategory = $catalogCategory;
-        $this->categoryFlatState = $categoryFlatState;
-        $this->menuCategoryData = $menuCategoryData;
+        $this->collectionFactory = $categoryCollectionFactory;
+        $this->storeManager = $storeManager;
+        $this->layerResolver = $layerResolver;
     }
 
     /**
@@ -50,38 +66,96 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
     public function execute(\Magento\Framework\Event\Observer $observer)
     {
         $block = $observer->getEvent()->getBlock();
-        $block->addIdentity(\Magento\Catalog\Model\Category::CACHE_TAG);
-        $this->_addCategoriesToMenu($this->catalogCategory->getStoreCategories(), $observer->getMenu(), $block);
+        $menuRootNode = $observer->getEvent()->getMenu();
+        $block->addIdentity(Category::CACHE_TAG);
+
+        $rootId = $this->storeManager->getStore()->getRootCategoryId();
+        $storeId = $this->storeManager->getStore()->getId();
+
+        /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
+        $collection = $this->getCategoryTree($storeId, $rootId);
+
+        $currentCategory = $this->getCurrentCategory();
+
+        $mapping = [$rootId => $menuRootNode];  // use nodes stack to avoid recursion
+        foreach ($collection as $category) {
+            if (!isset($mapping[$category->getParentId()])) {
+                continue;
+            }
+            /** @var Node $parentCategoryNode */
+            $parentCategoryNode = $mapping[$category->getParentId()];
+
+            $categoryNode = new Node(
+                $this->getCategoryAsArray($category, $currentCategory),
+                'id',
+                $parentCategoryNode->getTree(),
+                $parentCategoryNode
+            );
+            $parentCategoryNode->addChild($categoryNode);
+
+            $mapping[$category->getId()] = $categoryNode; //add node in stack
+
+            $block->addIdentity(Category::CACHE_TAG . '_' . $category->getId());
+        }
     }
 
     /**
-     * Recursively adds categories to top menu
+     * Get current Category from catalog layer
      *
-     * @param \Magento\Framework\Data\Tree\Node\Collection|array $categories
-     * @param \Magento\Framework\Data\Tree\Node $parentCategoryNode
-     * @param \Magento\Theme\Block\Html\Topmenu $block
-     * @return void
+     * @return \Magento\Catalog\Model\Category
      */
-    protected function _addCategoriesToMenu($categories, $parentCategoryNode, $block)
+    private function getCurrentCategory()
     {
-        foreach ($categories as $category) {
-            if (!$category->getIsActive()) {
-                continue;
-            }
-            $block->addIdentity(\Magento\Catalog\Model\Category::CACHE_TAG . '_' . $category->getId());
+        $catalogLayer = $this->layerResolver->get();
 
-            $tree = $parentCategoryNode->getTree();
-            $categoryData = $this->menuCategoryData->getMenuCategoryData($category);
-            $categoryNode = new \Magento\Framework\Data\Tree\Node($categoryData, 'id', $tree, $parentCategoryNode);
-            $parentCategoryNode->addChild($categoryNode);
+        if (!$catalogLayer) {
+            return null;
+        }
 
-            if ($this->categoryFlatState->isFlatEnabled() && $category->getUseFlatResource()) {
-                $subcategories = (array)$category->getChildrenNodes();
-            } else {
-                $subcategories = $category->getChildren();
-            }
+        return $catalogLayer->getCurrentCategory();
+    }
 
-            $this->_addCategoriesToMenu($subcategories, $categoryNode, $block);
-        }
+    /**
+     * Convert category to array
+     *
+     * @param \Magento\Catalog\Model\Category $category
+     * @param \Magento\Catalog\Model\Category $currentCategory
+     * @return array
+     */
+    private function getCategoryAsArray($category, $currentCategory)
+    {
+        return [
+            'name' => $category->getName(),
+            'id' => 'category-node-' . $category->getId(),
+            'url' => $this->catalogCategory->getCategoryUrl($category),
+            'has_active' => in_array((string)$category->getId(), explode('/', $currentCategory->getPath()), true),
+            'is_active' => $category->getId() == $currentCategory->getId()
+        ];
+    }
+
+    /**
+     * Get Category Tree
+     *
+     * @param int $storeId
+     * @param int $rootId
+     * @return \Magento\Catalog\Model\ResourceModel\Category\Collection
+     * @throws \Magento\Framework\Exception\LocalizedException
+     */
+    protected function getCategoryTree($storeId, $rootId)
+    {
+        /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
+        $collection = $this->collectionFactory->create();
+        $collection->setStoreId($storeId);
+        $collection->addAttributeToSelect('name');
+        $collection->addFieldToFilter('path', ['like' => '1/' . $rootId . '/%']); //load only from store root
+        $collection->addAttributeToFilter('include_in_menu', 1);
+        $collection->addAttributeToFilter('is_active', 1);
+        $collection->addUrlRewriteToResult();
+        $collection->addOrder('level', Collection::SORT_ORDER_ASC);
+        $collection->addOrder('position', Collection::SORT_ORDER_ASC);
+        $collection->addOrder('parent_id', Collection::SORT_ORDER_ASC);
+        $collection->addOrder('entity_id', Collection::SORT_ORDER_ASC);
+
+        return $collection;
     }
 }
diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php b/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php
index f8a9b12083b16710f78a60b616124b8871b94180..e0eb21a8bba306a258a26440a5cf957438427c5e 100644
--- a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php
@@ -52,14 +52,6 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
             false
         );
 
-        $this->_categoryFlatState = $this->getMock(
-            '\Magento\Catalog\Model\Indexer\Category\Flat\State',
-            ['isFlatEnabled'],
-            [],
-            '',
-            false
-        );
-
         $this->menuCategoryData = $this->getMock(
             'Magento\Catalog\Observer\MenuCategoryData',
             ['getMenuCategoryData'],
@@ -67,12 +59,44 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+
+        $this->store = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->setMethods(['getRootCategoryId', 'getFilters', '__wakeup'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
+            ->setMethods(['getStore'])
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $this->storeManager->expects($this->any())->method('getStore')
+            ->will($this->returnValue($this->store));
+
+        $this->store->expects($this->any())->method('getRootCategoryId')
+            ->will($this->returnValue(1));
+
+        $collectionFactory = $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory')
+            ->setMethods(['create'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $collection =  $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Category\Collection')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $collectionFactory->expects($this->once())->method('create')
+            ->willReturn($collection);
+
+        $collection->expects($this->once())->method('getIterator')
+            ->willReturn(new \ArrayIterator([]));
+
         $this->_observer = (new ObjectManager($this))->getObject(
             'Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver',
             [
                 'catalogCategory' => $this->_catalogCategory,
                 'menuCategoryData' => $this->menuCategoryData,
-                'categoryFlatState' => $this->_categoryFlatState,
+                'storeManager' => $this->storeManager,
+                'categoryCollectionFactory' => $collectionFactory,
             ]
         );
     }
@@ -97,9 +121,7 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->_childrenCategory->expects($this->once())
-            ->method('getIsActive')
-            ->will($this->returnValue(false));
+
 
         $this->_category = $this->getMock(
             '\Magento\Catalog\Model\Category',
@@ -108,69 +130,27 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
-        $this->_category->expects($this->once())
-            ->method('getIsActive')
-            ->will($this->returnValue(true));
-
-        $this->_catalogCategory->expects($this->once())
-            ->method('getStoreCategories')
-            ->will($this->returnValue([$this->_category]));
-        $this->menuCategoryData->expects($this->once())
-            ->method('getMenuCategoryData')
-            ->with($this->_category);
 
         $blockMock = $this->_getCleanMock('\Magento\Theme\Block\Html\Topmenu');
 
-        $treeMock = $this->_getCleanMock('\Magento\Framework\Data\Tree');
-
-        $menuMock = $this->getMock('\Magento\Framework\Data\Tree\Node', ['getTree', 'addChild'], [], '', false);
-        $menuMock->expects($this->once())
-            ->method('getTree')
-            ->will($this->returnValue($treeMock));
-
         $eventMock = $this->getMock('\Magento\Framework\Event', ['getBlock'], [], '', false);
         $eventMock->expects($this->once())
             ->method('getBlock')
             ->will($this->returnValue($blockMock));
 
         $observerMock = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent', 'getMenu'], [], '', false);
-        $observerMock->expects($this->once())
+        $observerMock->expects($this->any())
             ->method('getEvent')
             ->will($this->returnValue($eventMock));
-        $observerMock->expects($this->once())
-            ->method('getMenu')
-            ->will($this->returnValue($menuMock));
 
         return $observerMock;
     }
 
-    public function testAddCatalogToTopMenuItemsWithoutFlat()
+    public function testAddCatalogToTopMenuItems()
     {
         $observer = $this->_preparationData();
-
-        $this->_category->expects($this->once())
-            ->method('getChildren')
-            ->will($this->returnValue([$this->_childrenCategory]));
-
         $this->_observer->execute($observer);
     }
 
-    public function testAddCatalogToTopMenuItemsWithFlat()
-    {
-        $observer = $this->_preparationData();
-
-        $this->_category->expects($this->once())
-            ->method('getChildrenNodes')
-            ->will($this->returnValue([$this->_childrenCategory]));
-
-        $this->_category->expects($this->once())
-            ->method('getUseFlatResource')
-            ->will($this->returnValue(true));
 
-        $this->_categoryFlatState->expects($this->once())
-            ->method('isFlatEnabled')
-            ->will($this->returnValue(true));
-
-        $this->_observer->execute($observer);
-    }
 }
diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js
index 28f0ec5842a38dd7e63a3918f6e48fc04b7568ec..f1e3e33a99af289ce72a55e41238776843989dfc 100644
--- a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js
+++ b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js
@@ -339,7 +339,7 @@ define([
                     checkbox: 'input[id$=_price_use_default]',
                     label: 'span'
                 });
-                //@TODO not work set default value for second field
+                //not work set default value for second field
                 priceType.useDefault({
                     field: '.field',
                     useDefault: 'label[for$=_price]',
diff --git a/app/code/Magento/Catalog/view/frontend/templates/js/components.phtml b/app/code/Magento/Catalog/view/base/templates/js/components.phtml
similarity index 100%
rename from app/code/Magento/Catalog/view/frontend/templates/js/components.phtml
rename to app/code/Magento/Catalog/view/base/templates/js/components.phtml
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php
index d35fafee492d8408e0c9e7d00b41afa823396566..d63f6a63f455a0ac7caa488485a9a4954ccbb6dd 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php
@@ -173,6 +173,7 @@ class Set extends \Magento\Framework\Model\AbstractExtensibleModel implements
      *
      * @param array $data
      * @return $this
+     * @throws LocalizedException
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      */
@@ -220,10 +221,17 @@ class Set extends \Magento\Framework\Model\AbstractExtensibleModel implements
 
         if ($data['not_attributes']) {
             $modelAttributeArray = [];
-            foreach ($data['not_attributes'] as $attributeId) {
-                $modelAttribute = $this->_attributeFactory->create();
-
-                $modelAttribute->setEntityAttributeId($attributeId);
+            $data['not_attributes'] = array_filter($data['not_attributes']);
+            foreach ($data['not_attributes'] as $entityAttributeId) {
+                $entityAttribute = $this->_resourceAttribute->getEntityAttribute($entityAttributeId);
+                if (!$entityAttribute) {
+                    throw new LocalizedException(__('Entity attribute with id "%1" not found', $entityAttributeId));
+                }
+                $modelAttribute = $this->_eavConfig->getAttribute(
+                    $this->getEntityTypeId(),
+                    $entityAttribute['attribute_id']
+                );
+                $modelAttribute->setEntityAttributeId($entityAttributeId);
                 $modelAttributeArray[] = $modelAttribute;
             }
             $this->setRemoveAttributes($modelAttributeArray);
diff --git a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php
index 46d4c57cf0a7a1c3602af0de224f638be4a0df11..47fe17eed63c0db64e048f35505d24832e75c287 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute.php
@@ -133,10 +133,10 @@ class Attribute extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
     /**
      * Delete entity
      *
-     * @param AbstractModel $object
+     * @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object
      * @return $this
      */
-    public function deleteEntity(AbstractModel $object)
+    public function deleteEntity(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object)
     {
         if (!$object->getEntityAttributeId()) {
             return $this;
@@ -485,6 +485,23 @@ class Attribute extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
         return $connection->fetchOne($select, $bind);
     }
 
+    /**
+     * Get entity attribute
+     *
+     * @param int|string $entityAttributeId
+     * @return array
+     */
+    public function getEntityAttribute($entityAttributeId)
+    {
+        $select = $this->getConnection()->select()->from(
+            $this->getTable('eav_entity_attribute')
+        )->where(
+            'entity_attribute_id = ?',
+            (int)$entityAttributeId
+        );
+        return $this->getConnection()->fetchRow($select);
+    }
+
     /**
      * Retrieve attribute codes by front-end type
      *
diff --git a/app/code/Magento/Eav/etc/di.xml b/app/code/Magento/Eav/etc/di.xml
index 1bd5d307d419866b0c32e37a9eda6b562ba84323..809829ce6df0bc8e659988844ff6f853910b3862 100644
--- a/app/code/Magento/Eav/etc/di.xml
+++ b/app/code/Magento/Eav/etc/di.xml
@@ -89,4 +89,8 @@
             <argument name="contextHandler" xsi:type="object">Magento\Eav\Model\ResourceModel\ContextHandler</argument>
         </arguments>
     </type>
+    <type name="Magento\Eav\Model\Entity\AbstractEntity">
+        <plugin name="clean_cache" type="Magento\Framework\App\Cache\FlushCacheByTags" />
+    </type>
 </config>
+
diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php
index bacb704627493e1872c570539a8898bf679492b2..8b86ee29a86d29e78786291c29dcc2ba733ec3d3 100644
--- a/app/code/Magento/Theme/Block/Html/Topmenu.php
+++ b/app/code/Magento/Theme/Block/Html/Topmenu.php
@@ -49,6 +49,7 @@ class Topmenu extends Template implements IdentityInterface
         TreeFactory $treeFactory,
         array $data = []
     ) {
+        $this->setCacheLifetime(30 * 60);
         parent::__construct($context, $data);
         $this->_menu = $nodeFactory->create(
             [
@@ -85,7 +86,6 @@ class Topmenu extends Template implements IdentityInterface
             ['menu' => $this->_menu, 'transportObject' => $transportObject]
         );
         $html = $transportObject->getHtml();
-
         return $html;
     }
 
@@ -333,4 +333,26 @@ class Topmenu extends Template implements IdentityInterface
     {
         return $this->identities;
     }
+
+    /**
+     * Get cache key informative items
+     *
+     * @return array
+     */
+    public function getCacheKeyInfo()
+    {
+        $keyInfo = parent::getCacheKeyInfo();
+        $keyInfo[] = $this->getUrl('*/*/*', ['_current' => true, '_query' => '']);
+        return $keyInfo;
+    }
+
+    /**
+     * Get tags array for saving cache
+     *
+     * @return array
+     */
+    protected function getCacheTags()
+    {
+        return array_merge(parent::getCacheTags(), $this->getIdentities());
+    }
 }
diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
index d8b18edafa1232efddaccad35d35947af39cf8ed..b8260963ecbd7cc79d910ded6a0e07996c91acf8 100644
--- a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
@@ -14,6 +14,11 @@ use Magento\Framework\Data\Tree\NodeFactory;
 
 class TopmenuTest extends \PHPUnit_Framework_TestCase
 {
+    /**
+     * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $urlBuilder;
+
     /**
      * @var Registry|\PHPUnit_Framework_MockObject_MockObject
      */
@@ -51,15 +56,71 @@ HTML;
 <li  class="level0 nav-1 first active"><a href="http://magento2/category-0.html" ><span></span></a></li><li  class="level0 nav-2"><a href="http://magento2/category-1.html" ><span></span></a></li><li  class="level0 nav-3"><a href="http://magento2/category-2.html" ><span></span></a></li><li  class="level0 nav-4"><a href="http://magento2/category-3.html" ><span></span></a></li><li  class="level0 nav-5"><a href="http://magento2/category-4.html" ><span></span></a></li><li  class="level0 nav-6"><a href="http://magento2/category-5.html" ><span></span></a></li><li  class="level0 nav-7"><a href="http://magento2/category-6.html" ><span></span></a></li><li  class="level0 nav-8"><a href="http://magento2/category-7.html" ><span></span></a></li><li  class="level0 nav-9"><a href="http://magento2/category-8.html" ><span></span></a></li><li  class="level0 nav-10 last"><a href="http://magento2/category-9.html" ><span></span></a></li>
 HTML;
 
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManager;
+
     // @codingStandardsIgnoreEnd
 
     public function setUp()
     {
-        $isCurrentItem = $this->getName() == 'testGetHtmlWithSelectedCategory' ? true : false;
+
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
+            ->getMockForAbstractClass();
+
+        $this->urlBuilder = $this->getMockBuilder(\Magento\Framework\UrlInterface::class)->getMockForAbstractClass();
+        $this->context = $objectManager->getObject(
+            'Magento\Framework\View\Element\Template\Context',
+            ['urlBuilder' => $this->urlBuilder, 'storeManager' => $this->storeManager]
+        );
 
-        $this->context = $objectManager->getObject('Magento\Framework\View\Element\Template\Context');
+    }
 
+    protected function getTopmenu()
+    {
+        return new Topmenu($this->context, $this->nodeFactory, $this->treeFactory);
+    }
+
+    public function testGetHtmlWithoutSelectedCategory()
+    {
+        $this->buildTree(false);
+        $this->assertEquals($this->htmlWithoutCategory, $this->getTopmenu()->getHtml());
+    }
+
+    public function testGetHtmlWithSelectedCategory()
+    {
+        $this->buildTree(true);
+        $this->assertEquals($this->htmlWithCategory, $this->getTopmenu()->getHtml());
+    }
+
+    public function testGetCacheKeyInfo()
+    {
+        $nodeFactory = $this->getMock('Magento\Framework\Data\Tree\NodeFactory', [], [], '', false);
+        $treeFactory = $this->getMock('Magento\Framework\Data\TreeFactory', [], [], '', false);
+
+        $topmenu =  new Topmenu($this->context, $nodeFactory, $treeFactory);
+        $this->urlBuilder->expects($this->once())->method('getUrl')->with('*/*/*')->willReturn('123');
+        $store = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->setMethods(['getCode'])
+            ->getMock();
+        $store->expects($this->once())->method('getCode')->willReturn('321');
+        $this->storeManager->expects($this->once())->method('getStore')->willReturn($store);
+
+        $this->assertEquals(
+            ['BLOCK_TPL', '321', null, 'template' => null, '123'],
+            $topmenu->getCacheKeyInfo()
+        );
+    }
+
+    /**
+     * @param $isCurrentItem
+     * @return void
+     */
+    private function buildTree($isCurrentItem)
+    {
         $this->nodeFactory = $this->getMock('Magento\Framework\Data\Tree\NodeFactory', [], [], '', false);
         $this->treeFactory = $this->getMock('Magento\Framework\Data\TreeFactory', [], [], '', false);
 
@@ -76,14 +137,8 @@ HTML;
         for ($i = 0; $i < 10; $i++) {
             $id = "category-node-$i";
             $categoryNode = $this->getMock('Magento\Framework\Data\Tree\Node', ['getId', 'hasChildren'], [], '', false);
-            $categoryNode
-                ->expects($this->once())
-                ->method('getId')
-                ->willReturn($id);
-            $categoryNode
-                ->expects($this->atLeastOnce())
-                ->method('hasChildren')
-                ->willReturn(false);
+            $categoryNode->expects($this->once())->method('getId')->willReturn($id);
+            $categoryNode->expects($this->atLeastOnce())->method('hasChildren')->willReturn(false);
             $categoryNode->setData(
                 [
                     'name' => "Category $i",
@@ -97,45 +152,14 @@ HTML;
             $children->add($categoryNode);
         }
 
-        $children
-            ->expects($this->once())
-            ->method('count')
-            ->willReturn(10);
+        $children->expects($this->once())->method('count')->willReturn(10);
 
         $node = $this->getMock('Magento\Framework\Data\Tree\Node', ['getChildren'], [], '', false);
-        $node
-            ->expects($this->once())
-            ->method('getChildren')
-            ->willReturn($children);
-        $node
-            ->expects($this->any())
-            ->method('__call')
-            ->with('getLevel', [])
-            ->willReturn(null);
-
-        $this->nodeFactory
-            ->expects($this->once())
-            ->method('create')
-            ->willReturn($node);
-
-        $this->treeFactory
-            ->expects($this->once())
-            ->method('create')
-            ->willReturn($tree);
-    }
-
-    protected function getTopmenu()
-    {
-        return new Topmenu($this->context, $this->nodeFactory, $this->treeFactory);
-    }
+        $node->expects($this->once())->method('getChildren')->willReturn($children);
+        $node->expects($this->any())->method('__call')->with('getLevel', [])->willReturn(null);
 
-    public function testGetHtmlWithoutSelectedCategory()
-    {
-        $this->assertEquals($this->htmlWithoutCategory, $this->getTopmenu()->getHtml());
-    }
+        $this->nodeFactory->expects($this->once())->method('create')->willReturn($node);
 
-    public function testGetHtmlWithSelectedCategory()
-    {
-        $this->assertEquals($this->htmlWithCategory, $this->getTopmenu()->getHtml());
+        $this->treeFactory->expects($this->once())->method('create')->willReturn($tree);
     }
 }
diff --git a/app/code/Magento/Theme/view/frontend/templates/html/topmenu.phtml b/app/code/Magento/Theme/view/frontend/templates/html/topmenu.phtml
index 6f8c7965c4412df8b866505bb01294536e429f40..15067b664c252cbfb43d43de192296a2eb70f20b 100644
--- a/app/code/Magento/Theme/view/frontend/templates/html/topmenu.phtml
+++ b/app/code/Magento/Theme/view/frontend/templates/html/topmenu.phtml
@@ -11,7 +11,7 @@
 /**
  * Top menu for store
  *
- * @see \Magento\Theme\Block\Html\Topmenu
+ * @var $block \Magento\Theme\Block\Html\Topmenu
  */
 ?>
 <?php $columnsLimit = $block->getColumnsLimit() ?: 0; ?>
@@ -20,5 +20,6 @@
 <nav class="navigation" data-action="navigation">
     <ul data-mage-init='{"menu":{"responsive":true, "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'>
         <?php /* @escapeNotVerified */ echo $_menu; ?>
+        <?php /* @escapeNotVerified */ echo $block->getChildHtml(); ?>
     </ul>
 </nav>
diff --git a/app/etc/di.xml b/app/etc/di.xml
index 8bdf6e4d498b8d949117eef496c99d96ceb9adc3..3aa20b5c0331a4f0f658c4480e57a724709c289c 100755
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -1174,4 +1174,14 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\App\Cache\FlushCacheByTags">
+        <arguments>
+            <argument name="cacheList" xsi:type="array">
+                <item name="block_html" xsi:type="const">Magento\Framework\App\Cache\Type\Block::TYPE_IDENTIFIER</item>
+            </argument>
+        </arguments>
+    </type>
+    <type name="Magento\Framework\Model\ResourceModel\Db\AbstractDb">
+        <plugin name="clean_cache" type="Magento\Framework\App\Cache\FlushCacheByTags" />
+    </type>
 </config>
diff --git a/lib/internal/Magento/Framework/App/Cache/FlushCacheByTags.php b/lib/internal/Magento/Framework/App/Cache/FlushCacheByTags.php
new file mode 100644
index 0000000000000000000000000000000000000000..468000e7de4125e83a9de8c17a3dae57dbcdbbca
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Cache/FlushCacheByTags.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\App\Cache;
+
+/**
+ * Automatic cache cleaner plugin
+ */
+class FlushCacheByTags
+{
+    /**
+     * @var Type\FrontendPool
+     */
+    private $cachePool;
+
+    /**
+     * @var array
+     */
+    private $cacheList;
+
+    /**
+     * @var StateInterface
+     */
+    private $cacheState;
+
+    /**
+     * FlushCacheByTags constructor.
+     *
+     * @param Type\FrontendPool $cachePool
+     * @param StateInterface $cacheState
+     * @param array $cacheList
+     */
+    public function __construct(
+        \Magento\Framework\App\Cache\Type\FrontendPool $cachePool,
+        \Magento\Framework\App\Cache\StateInterface $cacheState,
+        array $cacheList
+    ) {
+        $this->cachePool = $cachePool;
+        $this->cacheState = $cacheState;
+        $this->cacheList = $cacheList;
+    }
+
+    /**
+     * Clean cache on save object
+     *
+     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $subject
+     * @param \Closure $proceed
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return \Magento\Framework\Model\ResourceModel\AbstractResource
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function aroundSave(
+        \Magento\Framework\Model\ResourceModel\AbstractResource $subject,
+        \Closure $proceed,
+        \Magento\Framework\Model\AbstractModel $object
+    ) {
+        $result = $proceed($object);
+        if ($object instanceof \Magento\Framework\DataObject\IdentityInterface) {
+            $this->cleanCacheByTags($object->getIdentities());
+        }
+        return $result;
+    }
+
+    /**
+     * Clean cache on delete object
+     *
+     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $subject
+     * @param \Closure $proceed
+     * @param \Magento\Framework\Model\AbstractModel $object
+     * @return \Magento\Framework\Model\ResourceModel\AbstractResource
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function aroundDelete(
+        \Magento\Framework\Model\ResourceModel\AbstractResource $subject,
+        \Closure $proceed,
+        \Magento\Framework\Model\AbstractModel $object
+    ) {
+        $tags = [];
+        if ($object instanceof \Magento\Framework\DataObject\IdentityInterface) {
+            $tags = $object->getIdentities();
+        }
+        $result = $proceed($object);
+        $this->cleanCacheByTags($tags);
+        return $result;
+    }
+
+    /**
+     * Clean cache by tags
+     *
+     * @param  string[] $tags
+     * @return void
+     */
+    private function cleanCacheByTags($tags)
+    {
+        if (empty($tags)) {
+            return;
+        }
+        foreach ($this->cacheList as $cacheType) {
+            if ($this->cacheState->isEnabled($cacheType)) {
+                $this->cachePool->get($cacheType)->clean(
+                    \Zend_Cache::CLEANING_MODE_MATCHING_TAG,
+                    array_unique($tags)
+                );
+            }
+        }
+    }
+}
diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Cache/FlushCacheByTagsTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Cache/FlushCacheByTagsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..902df102283cb0900f24deef645c08ec4c9e2abf
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Test/Unit/Cache/FlushCacheByTagsTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: akasian
+ * Date: 1/25/16
+ * Time: 10:26 AM
+ */
+
+namespace Magento\Framework\App\Test\Unit\Cache;
+
+class FlushCacheByTagsTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Cache\StateInterface
+     */
+    private $cacheState;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Cache\Type\FrontendPool
+     */
+    private $frontendPool;
+
+    /**
+     * @var \Magento\Framework\App\Cache\FlushCacheByTags
+     */
+    private $plugin;
+
+    protected function setUp()
+    {
+        $this->cacheState = $this->getMockForAbstractClass(\Magento\Framework\App\Cache\StateInterface::class);
+        $this->frontendPool = $this->getMock(\Magento\Framework\App\Cache\Type\FrontendPool::class, [], [], '', false);
+        $this->plugin = new \Magento\Framework\App\Cache\FlushCacheByTags(
+            $this->frontendPool,
+            $this->cacheState,
+            ['test']
+        );
+
+    }
+
+    public function testAroundSave()
+    {
+        $resource = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\AbstractResource::class)
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $result = $this->plugin->aroundSave(
+            $resource,
+            function () use ($resource) {
+                return $resource;
+            },
+            $model
+        );
+        $this->assertSame($resource, $result);
+    }
+
+    public function testAroundDelete()
+    {
+        $resource = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\AbstractResource::class)
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $result = $this->plugin->aroundDelete(
+            $resource,
+            function () use ($resource) {
+                return $resource;
+            },
+            $model
+        );
+        $this->assertSame($resource, $result);
+    }
+
+    public function testAroundSaveWithInterface()
+    {
+        $resource = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\AbstractResource::class)
+
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $model = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class)
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+        $result = $this->plugin->aroundSave(
+            $resource,
+            function () use ($resource) {
+                return $resource;
+            },
+            $model
+        );
+        $this->assertSame($resource, $result);
+    }
+}
diff --git a/lib/internal/Magento/Framework/Url/QueryParamsResolver.php b/lib/internal/Magento/Framework/Url/QueryParamsResolver.php
index 075ecfe0d4ee9bded7c543d1ce3a147d76752578..c74cbbfab9e82b010d13c3dc8819e1f79a116fd0 100644
--- a/lib/internal/Magento/Framework/Url/QueryParamsResolver.php
+++ b/lib/internal/Magento/Framework/Url/QueryParamsResolver.php
@@ -29,7 +29,7 @@ class QueryParamsResolver extends \Magento\Framework\DataObject implements Query
      */
     public function setQuery($data)
     {
-        if ($this->_getData('query') != $data) {
+        if ($this->_getData('query') !== $data) {
             $this->unsetData('query_params');
             $this->setData('query', $data);
         }
diff --git a/setup/src/Magento/Setup/Test/Unit/Fixtures/StoresFixtureTest.php b/setup/src/Magento/Setup/Test/Unit/Fixtures/StoresFixtureTest.php
index 07cd715489eab46621edfc68ae1a332c5678d5d3..bd8d4022d063794ba5d8a0f530ab93cf55311da1 100644
--- a/setup/src/Magento/Setup/Test/Unit/Fixtures/StoresFixtureTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Fixtures/StoresFixtureTest.php
@@ -75,7 +75,6 @@ class StoresFixtureTest extends \PHPUnit_Framework_TestCase
         $categoryMock = $this->getMock(
             'Magento\Catalog\Model\Category',
             [
-                'setId',
                 'setName',
                 'setPath',
                 'setLevel',
@@ -83,15 +82,13 @@ class StoresFixtureTest extends \PHPUnit_Framework_TestCase
                 'setDefaultSortBy',
                 'setIsActive',
                 'getId',
-                'save'
+                'save',
+                'load'
             ],
             [],
             '',
             false
         );
-        $categoryMock->expects($this->once())
-            ->method('setId')
-            ->willReturnSelf();
         $categoryMock->expects($this->once())
             ->method('setName')
             ->willReturnSelf();