diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index 0d8d18df223767b2812f58356de3b7904090d8f7..1841a9efb6cf8424ebc7ef0b289495388da31db2 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -8,6 +8,7 @@ namespace Magento\Eav\Model\Entity\Attribute;
 
 use Magento\Framework\Api\AttributeValueFactory;
 use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Serialize\SerializerInterface;
 
 /**
  * Entity/Attribute/Model - attribute abstract
@@ -22,6 +23,11 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
 {
     const TYPE_STATIC = 'static';
 
+    /**
+     * Const for empty string value.
+     */
+    const EMPTY_STRING = '';
+
     /**
      * Attribute name
      *
@@ -111,6 +117,27 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
      */
     protected $dataObjectHelper;
 
+    /**
+     * Serializer Instance.
+     *
+     * @var SerializerInterface
+     */
+    private $serializer;
+
+    /**
+     * Array of attribute types that have empty string as a possible value.
+     *
+     * @var array
+     */
+    private $emptyStringTypes = [
+        'int',
+        'decimal',
+        'datetime',
+        'varchar',
+        'text',
+        'static',
+    ];
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -166,6 +193,21 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         $this->dataObjectHelper = $dataObjectHelper;
     }
 
+    /**
+     * Get Serializer instance.
+     * @deprecated
+     *
+     * @return SerializerInterface
+     */
+    private function getSerializer()
+    {
+        if ($this->serializer === null) {
+            $this->serializer = \Magento\Framework\App\ObjectManager::getInstance()->create(SerializerInterface::class);
+        }
+
+        return $this->serializer;
+    }
+
     /**
      * Initialize resource model
      *
@@ -202,6 +244,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         $this->_getResource()->loadByCode($this, $entityTypeId, $code);
         $this->_afterLoad();
         \Magento\Framework\Profiler::stop('load_by_code');
+
         return $this;
     }
 
@@ -226,6 +269,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function setAttributeId($data)
     {
         $this->_data['attribute_id'] = $data;
+
         return $this;
     }
 
@@ -372,6 +416,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function setAttributeSetId($id)
     {
         $this->_data['attribute_set_id'] = $id;
+
         return $this;
     }
 
@@ -392,6 +437,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function setEntityTypeId($id)
     {
         $this->_data['entity_type_id'] = $id;
+
         return $this;
     }
 
@@ -403,6 +449,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function setEntityType($type)
     {
         $this->setData('entity_type', $type);
+
         return $this;
     }
 
@@ -456,6 +503,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function setEntity($entity)
     {
         $this->_entity = $entity;
+
         return $this;
     }
 
@@ -469,6 +517,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         if (!$this->_entity) {
             $this->_entity = $this->getEntityType();
         }
+
         return $this->_entity;
     }
 
@@ -546,6 +595,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
             }
             $this->_source = $source->setAttribute($this);
         }
+
         return $this->_source;
     }
 
@@ -557,6 +607,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     public function usesSource()
     {
         $input = $this->getFrontendInput();
+
         return $input === 'select' || $input === 'multiselect' || $this->_getData('source_model') != '';
     }
 
@@ -588,17 +639,38 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
     }
 
     /**
+     * Check if Value is empty.
+     *
      * @param array|null|bool|int|float|string $value
      * @return bool
      */
     public function isValueEmpty($value)
     {
-        /** @var array $emptyStringTypes list of attribute types that treat empty string as a possible value */
-        $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static'];
         return (is_array($value) && count($value) == 0)
             || $value === null
             || ($value === false && $this->getBackend()->getType() != 'int')
-            || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes));
+            || ($value === self::EMPTY_STRING && $this->isInEmptyStringTypes());
+    }
+
+    /**
+     * Check if attribute empty value is valid.
+     *
+     * @param array|null|bool|int|float|string $value
+     * @return bool
+     */
+    public function isAllowedEmptyTextValue($value)
+    {
+        return $this->isInEmptyStringTypes() && $value === self::EMPTY_STRING;
+    }
+
+    /**
+     * Check is attribute type in allowed empty string types.
+     *
+     * @return bool
+     */
+    private function isInEmptyStringTypes()
+    {
+        return in_array($this->getBackend()->getType(), $this->emptyStringTypes);
     }
 
     /**
@@ -654,6 +726,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         if (!isset($this->_attributeIdCache[$cacheKey])) {
             $this->_attributeIdCache[$cacheKey] = $this->getResource()->getIdByCode($entityType, $code);
         }
+
         return $this->_attributeIdCache[$cacheKey];
     }
 
@@ -686,6 +759,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
                 $this->_dataTable = $backendTable;
             }
         }
+
         return $this->_dataTable;
     }
 
@@ -700,6 +774,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         if ($this->usesSource() && $this->getBackendType() != self::TYPE_STATIC) {
             return $this->getSource()->getFlatColumns();
         }
+
         return $this->_getFlatColumnsDdlDefinition();
     }
 
@@ -723,60 +798,60 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
                 $size = $prop['LENGTH'] ? $prop['LENGTH'] : null;
 
                 $columns[$this->getAttributeCode()] = [
-                    'type' => $this->_resourceHelper->getDdlTypeByColumnType($type),
-                    'length' => $size,
+                    'type'     => $this->_resourceHelper->getDdlTypeByColumnType($type),
+                    'length'   => $size,
                     'unsigned' => $prop['UNSIGNED'] ? true : false,
                     'nullable' => $prop['NULLABLE'],
-                    'default' => $prop['DEFAULT'],
-                    'extra' => null,
+                    'default'  => $prop['DEFAULT'],
+                    'extra'    => null,
                 ];
                 break;
             case 'datetime':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME,
+                    'type'     => \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME,
                     'unsigned' => false,
                     'nullable' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'decimal':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
-                    'length' => '12,4',
+                    'type'     => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
+                    'length'   => '12,4',
                     'unsigned' => false,
                     'nullable' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'int':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
+                    'type'     => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                     'unsigned' => false,
                     'nullable' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'text':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+                    'type'     => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                     'unsigned' => false,
                     'nullable' => true,
-                    'default' => null,
-                    'extra' => null,
-                    'length' => \Magento\Framework\DB\Ddl\Table::MAX_TEXT_SIZE,
+                    'default'  => null,
+                    'extra'    => null,
+                    'length'   => \Magento\Framework\DB\Ddl\Table::MAX_TEXT_SIZE,
                 ];
                 break;
             case 'varchar':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
-                    'length' => '255',
+                    'type'     => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+                    'length'   => '255',
                     'unsigned' => false,
                     'nullable' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             default:
@@ -804,61 +879,62 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
                 }
                 $prop = $describe[$this->getAttributeCode()];
                 $columns[$this->getAttributeCode()] = [
-                    'type' => $prop['DATA_TYPE'] . ($prop['LENGTH'] ? "({$prop['LENGTH']})" : ""),
+                    'type'     => $prop['DATA_TYPE'] . ($prop['LENGTH'] ? "({$prop['LENGTH']})" : ""),
                     'unsigned' => $prop['UNSIGNED'] ? true : false,
-                    'is_null' => $prop['NULLABLE'],
-                    'default' => $prop['DEFAULT'],
-                    'extra' => null,
+                    'is_null'  => $prop['NULLABLE'],
+                    'default'  => $prop['DEFAULT'],
+                    'extra'    => null,
                 ];
                 break;
             case 'datetime':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => 'datetime',
+                    'type'     => 'datetime',
                     'unsigned' => false,
-                    'is_null' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'is_null'  => true,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'decimal':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => 'decimal(12,4)',
+                    'type'     => 'decimal(12,4)',
                     'unsigned' => false,
-                    'is_null' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'is_null'  => true,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'int':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => 'int',
+                    'type'     => 'int',
                     'unsigned' => false,
-                    'is_null' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'is_null'  => true,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'text':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => 'text',
+                    'type'     => 'text',
                     'unsigned' => false,
-                    'is_null' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'is_null'  => true,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             case 'varchar':
                 $columns[$this->getAttributeCode()] = [
-                    'type' => 'varchar(255)',
+                    'type'     => 'varchar(255)',
                     'unsigned' => false,
-                    'is_null' => true,
-                    'default' => null,
-                    'extra' => null,
+                    'is_null'  => true,
+                    'default'  => null,
+                    'extra'    => null,
                 ];
                 break;
             default:
                 break;
         }
+
         return $columns;
     }
 
@@ -945,6 +1021,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
             foreach ($this->_storeManager->getStores() as $store) {
                 $this->getFlatUpdateSelect($store->getId());
             }
+
             return $this;
         }
 
@@ -955,6 +1032,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         if ($this->usesSource()) {
             return $this->getSource()->getFlatUpdateSelect($store);
         }
+
         return $this->_getResource()->getFlatUpdateSelect($this, $store);
     }
 
@@ -1064,6 +1142,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         } else {
             $this->setData(self::OPTIONS, $options);
         }
+
         return $this;
     }
 
@@ -1086,6 +1165,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
             );
             $dataObjects[] = $optionDataObject;
         }
+
         return $dataObjects;
     }
 
@@ -1195,8 +1275,9 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
         if (is_array($rules)) {
             return $rules;
         } elseif (!empty($rules)) {
-            return unserialize($rules);
+            return $this->getSerializer()->unserialize($rules);
         }
+
         return [];
     }
 
diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
index c775a24a03c465dad45640a7f634823cb8b43ef8..bcaf11aaf5532be296fe19ac6d0bb451b6a20b13 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
@@ -125,55 +125,65 @@ class UpdateHandler implements AttributeInterface
                 : null; // @todo verify is it normal to not have attributer_set_id
             $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot);
             foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) {
-                if ($attribute->isStatic()) {
-                    continue;
-                }
-                /**
-                 * Only scalar values can be stored in generic tables
-                 */
-                if (isset($entityData[$attribute->getAttributeCode()])
-                    && !is_scalar($entityData[$attribute->getAttributeCode()])) {
+                $code = $attribute->getAttributeCode();
+                $isAllowedValueType = array_key_exists($code, $entityData)
+                    && (is_scalar($entityData[$code]) || $entityData[$code] === null);
+
+                if ($attribute->isStatic() || !$isAllowedValueType) {
                     continue;
                 }
-                if (isset($snapshot[$attribute->getAttributeCode()])
-                    && $snapshot[$attribute->getAttributeCode()] !== false
-                    && (array_key_exists($attribute->getAttributeCode(), $entityData)
-                        && $attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]))
-                ) {
-                    $this->attributePersistor->registerDelete(
-                        $entityType,
-                        $entityData[$metadata->getLinkField()],
-                        $attribute->getAttributeCode()
-                    );
-                }
-                if ((!array_key_exists($attribute->getAttributeCode(), $snapshot)
-                        || $snapshot[$attribute->getAttributeCode()] === false)
-                    && array_key_exists($attribute->getAttributeCode(), $entityData)
-                    && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])
-                ) {
-                    $this->attributePersistor->registerInsert(
-                        $entityType,
-                        $entityData[$metadata->getLinkField()],
-                        $attribute->getAttributeCode(),
-                        $entityData[$attribute->getAttributeCode()]
-                    );
-                }
-                if (array_key_exists($attribute->getAttributeCode(), $snapshot)
-                    && $snapshot[$attribute->getAttributeCode()] !== false
-                    && array_key_exists($attribute->getAttributeCode(), $entityData)
-                    && $snapshot[$attribute->getAttributeCode()] != $entityData[$attribute->getAttributeCode()]
-                    && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])
-                ) {
-                    $this->attributePersistor->registerUpdate(
-                        $entityType,
-                        $entityData[$metadata->getLinkField()],
-                        $attribute->getAttributeCode(),
-                        $entityData[$attribute->getAttributeCode()]
-                    );
+
+                $newValue = $entityData[$code];
+                $isValueEmpty = $attribute->isValueEmpty($newValue);
+                $isAllowedEmptyStringValue = $attribute->isAllowedEmptyTextValue($newValue);
+
+                if (array_key_exists($code, $snapshot)) {
+                    $snapshotValue = $snapshot[$code];
+                    /**
+                     * 'FALSE' value for attributes can't be update or delete
+                     */
+                    if ($snapshotValue === false) {
+                        continue;
+                    }
+
+                    if (!$isValueEmpty || $isAllowedEmptyStringValue) {
+                        /**
+                         * NOT Updated value for attributes not need to update
+                         */
+                        if ($snapshotValue === $newValue) {
+                            continue;
+                        }
+
+                        $this->attributePersistor->registerUpdate(
+                            $entityType,
+                            $entityData[$metadata->getLinkField()],
+                            $code,
+                            $newValue
+                        );
+                    } else {
+                        $this->attributePersistor->registerDelete(
+                            $entityType,
+                            $entityData[$metadata->getLinkField()],
+                            $code
+                        );
+                    }
+                } else {
+                    /**
+                     * Only not empty value of attribute is insertable
+                     */
+                    if (!$isValueEmpty || $isAllowedEmptyStringValue) {
+                        $this->attributePersistor->registerInsert(
+                            $entityType,
+                            $entityData[$metadata->getLinkField()],
+                            $code,
+                            $newValue
+                        );
+                    }
                 }
             }
             $this->attributePersistor->flush($entityType, $context);
         }
+
         return $this->getReadHandler()->execute($entityType, $entityData, $arguments);
     }
 
@@ -189,6 +199,7 @@ class UpdateHandler implements AttributeInterface
         if (!$this->readHandler) {
             $this->readHandler = ObjectManager::getInstance()->get(ReadHandler::class);
         }
+
         return $this->readHandler;
     }
 }
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
index a10bafacda42dc2b72fcc285307a0250cae3074b..3c0e77408ba2dfbbe68651107cfa1a1d7a885588 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
@@ -144,19 +144,33 @@ class AbstractAttributeTest extends \PHPUnit_Framework_TestCase
 
     public function testGetValidationRulesWhenRuleIsSerialized()
     {
-        $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
-        $rule = 'some value';
-        $model = $objectManagerHelper->getObject(
-            \Magento\Catalog\Model\Entity\Attribute::class,
-            [
-                'data' => [
-                    \Magento\Eav\Api\Data\AttributeInterface::VALIDATE_RULES => serialize($rule)
-                ]
+        $rule = serialize('some value');
+        $expected = 'some test result';
 
-            ]
-        );
+        $modelClassName = \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class;
+        $model = $this->getMockForAbstractClass($modelClassName, [], '', false);
 
-        $this->assertEquals($rule, $model->getValidationRules());
+        $serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class);
+
+        $reflection = new \ReflectionClass($modelClassName);
+        $reflectionProperty = $reflection->getProperty('serializer');
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($model, $serializerMock);
+
+        $model->setData(\Magento\Eav\Api\Data\AttributeInterface::VALIDATE_RULES, $rule);
+
+        $serializerMock->method('unserialize')
+            ->with($rule)
+            ->willReturn($expected);
+
+        $this->assertEquals($expected, $model->getValidationRules());
+
+        $data = ['test array'];
+        $model->setData(\Magento\Eav\Api\Data\AttributeInterface::VALIDATE_RULES, $data);
+        $this->assertEquals($data, $model->getValidationRules());
+
+        $model->setData(\Magento\Eav\Api\Data\AttributeInterface::VALIDATE_RULES, null);
+        $this->assertEquals([], $model->getValidationRules());
     }
 
     public function testGetValidationRulesWhenRuleIsEmpty()
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js
index 01c8ef29029a9ef34f82885e3efbada75774a88b..209b05773a497b8e02d36cdd4adba10eab107779 100644
--- a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js
@@ -93,7 +93,7 @@ define([
             /* eslint-disable no-undef */
             if (tinyMCE) {
                 _.each(tinyMCE.activeEditor.controlManager.controls, function (property, index, controls) {
-                    controls[property].setDisabled(status);
+                    controls[property.id].setDisabled(status);
                 });
 
                 tinyMCE.activeEditor.getBody().setAttribute('contenteditable', !status);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php
index f84c661126b04b9a30ec2ca84ef7d3f570d2a1bb..5db10afdee00284a4faa7249e273bb3d47ab5daf 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php
@@ -233,7 +233,7 @@ class CategoryTest extends \Magento\TestFramework\TestCase\AbstractBackendContro
                     'display_mode' => true,
                     'meta_title' => true,
                     'custom_design' => true,
-                    'page_layout' => false,
+                    'page_layout' => true,
                     'is_active' => true,
                     'include_in_menu' => true,
                     'landing_page' => true,
@@ -242,7 +242,7 @@ class CategoryTest extends \Magento\TestFramework\TestCase\AbstractBackendContro
                     'description' => true,
                     'meta_keywords' => true,
                     'meta_description' => true,
-                    'custom_layout_update' => false,
+                    'custom_layout_update' => true,
                     'custom_design_from' => true,
                     'custom_design_to' => true,
                     'filter_price_range' => false
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..56e84046b255bf89c5f6aa6c1cb75cb7c7d584ba
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/dropdown_attribute.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/* Create attribute */
+/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
+$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+    \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class
+);
+
+if (!$attribute->loadByCode(4, 'dropdown_attribute')->getId()) {
+    /** @var $installer \Magento\Catalog\Setup\CategorySetup */
+    $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+        \Magento\Catalog\Setup\CategorySetup::class
+    );
+
+    $attribute->setData(
+        [
+            'attribute_code'                => 'dropdown_attribute',
+            'entity_type_id'                => $installer->getEntityTypeId('catalog_product'),
+            'is_global'                     => 0,
+            'is_user_defined'               => 1,
+            'frontend_input'                => 'select',
+            'is_unique'                     => 0,
+            'is_required'                   => 0,
+            'is_searchable'                 => 0,
+            'is_visible_in_advanced_search' => 0,
+            'is_comparable'                 => 0,
+            'is_filterable'                 => 0,
+            'is_filterable_in_search'       => 0,
+            'is_used_for_promo_rules'       => 0,
+            'is_html_allowed_on_front'      => 1,
+            'is_visible_on_front'           => 0,
+            'used_in_product_listing'       => 0,
+            'used_for_sort_by'              => 0,
+            'frontend_label'                => ['Drop-Down Attribute'],
+            'backend_type'                  => 'varchar',
+            'backend_model'                 => \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class,
+            'option'                        => [
+                'value' => [
+                    'option_1' => ['Option 1'],
+                    'option_2' => ['Option 2'],
+                    'option_3' => ['Option 3'],
+                ],
+                'order' => [
+                    'option_1' => 1,
+                    'option_2' => 2,
+                    'option_3' => 3,
+                ],
+            ],
+        ]
+    );
+    $attribute->save();
+
+    /* Assign attribute to attribute set */
+    $installer->addAttributeToGroup('catalog_product', 'Default', 'Attributes', $attribute->getId());
+}
diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d5daf1e6aadfe7c5e55cc0444b9209dd533c5a1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ResourceModel/UpdateHandlerTest.php
@@ -0,0 +1,257 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Eav\Model\ResourceModel;
+
+use Magento\TestFramework\Helper\Bootstrap;
+
+/**
+ * @magentoAppArea adminhtml
+ * @magentoAppIsolation enabled
+ * @magentoDbIsolation enabled
+ */
+class UpdateHandlerTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @covers       \Magento\Eav\Model\ResourceModel\UpdateHandler::execute
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     * @dataProvider getAllStoresDataProvider
+     * @param $code
+     * @param $snapshotValue
+     * @param $newValue
+     * @param $expected
+     */
+    public function testExecuteProcessForAllStores($code, $snapshotValue, $newValue, $expected)
+    {
+        if ($snapshotValue !== '-') {
+            $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+            $entity->setStoreId(0);
+            $entity->load(1);
+            $entity->setData($code, $snapshotValue);
+            $entity->save();
+        }
+
+        $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $entity->setStoreId(0);
+        $entity->load(1);
+
+        $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class);
+        $entityData = array_merge($entity->getData(), [$code => $newValue]);
+        $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData);
+
+        $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $resultEntity->setStoreId(0);
+        $resultEntity->load(1);
+
+        $this->assertSame($expected, $resultEntity->getData($code));
+    }
+
+    /**
+     * @covers       \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoDataFixture Magento/Store/_files/second_store.php
+     * @dataProvider getCustomStoreDataProvider
+     * @param $code
+     * @param $snapshotValue
+     * @param $newValue
+     * @param $expected
+     */
+    public function testExecuteProcessForCustomStore($code, $snapshotValue, $newValue, $expected)
+    {
+        $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
+        $store->load('fixture_second_store', 'code');
+
+        Bootstrap::getObjectManager()
+            ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class)
+            ->reindexAll();
+
+        if ($snapshotValue !== '-') {
+            $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+            $entity->setStoreId($store->getId());
+            $entity->load(1);
+            $entity->setData($code, $snapshotValue);
+            $entity->save();
+        }
+
+        $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $entity->setStoreId($store->getId());
+        $entity->load(1);
+
+        $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class);
+        $entityData = array_merge($entity->getData(), [$code => $newValue]);
+        $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData);
+
+        $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $resultEntity->setStoreId($store->getId());
+        $resultEntity->load(1);
+
+        $this->assertSame($expected, $resultEntity->getData($code));
+    }
+
+    /**
+     * @covers       \Magento\Eav\Model\ResourceModel\UpdateHandlerTest::execute
+     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php
+     * @magentoDataFixture Magento/Store/_files/second_store.php
+     * @dataProvider getCustomAttributeDataProvider
+     * @param $code
+     * @param $defaultStoreValue
+     * @param $snapshotValue
+     * @param $newValue
+     * @param $expected
+     */
+    public function testExecuteProcessForCustomAttributeInCustomStore(
+        $code,
+        $defaultStoreValue,
+        $snapshotValue,
+        $newValue,
+        $expected
+    ) {
+        $store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
+        $store->load('fixture_second_store', 'code');
+
+        Bootstrap::getObjectManager()
+            ->create(\Magento\CatalogSearch\Model\Indexer\Fulltext\Processor::class)
+            ->reindexAll();
+
+        $attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class
+        );
+        $attribute->loadByCode(4, $code);
+
+        $options = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+            \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class
+        );
+        $options->setAttributeFilter($attribute->getId());
+        $optionIds = $options->getAllIds();
+
+        $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $entity->setStoreId(0);
+        $entity->load(1);
+        $entity->setData($code, $optionIds[$defaultStoreValue]);
+        $entity->save();
+
+        if ($snapshotValue !== '-') {
+            /** @var $options \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection */
+            $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+            $entity->setStoreId($store->getId());
+            $entity->load(1);
+
+            if ($snapshotValue) {
+                $snapshotValue = $optionIds[$snapshotValue];
+            }
+
+            $entity->setData($code, $snapshotValue);
+            $entity->save();
+        }
+
+        $entity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $entity->setStoreId($store->getId());
+        $entity->load(1);
+
+        $updateHandler = Bootstrap::getObjectManager()->create(UpdateHandler::class);
+
+        if ($newValue) {
+            $newValue = $optionIds[$newValue];
+        }
+
+        $entityData = array_merge($entity->getData(), [$code => $newValue]);
+        $updateHandler->execute(\Magento\Catalog\Api\Data\ProductInterface::class, $entityData);
+
+        $resultEntity = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
+        $resultEntity->setStoreId($store->getId());
+        $resultEntity->load(1);
+
+        if ($expected !== null) {
+            $expected = $optionIds[$expected];
+        }
+
+        $this->assertSame($expected, $resultEntity->getData($code));
+    }
+
+    /**
+     * @return array
+     */
+    public function getAllStoresDataProvider()
+    {
+        return [
+            ['description', '', 'not_empty_value', 'not_empty_value'],                  //0
+            ['description', '', '', null],                                              //1
+            ['description', '', null, null],                                            //2
+            ['description', '', false, null],                                           //3
+
+            ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4
+            ['description', 'not_empty_value', '', null],                               //5
+            ['description', 'not_empty_value', null, null],                             //6
+            ['description', 'not_empty_value', false, null],                            //7
+
+            ['description', null, 'not_empty_value', 'not_empty_value'],                //8
+            ['description', null, '', null],                                            //9
+            ['description', null, false, null],                                         //10
+
+            ['description', false, 'not_empty_value', 'not_empty_value'],               //11
+            ['description', false, '', null],                                           //12
+            ['description', false, null, null],                                         //13
+        ];
+    }
+
+    /**
+     * @return array
+     */
+    public function getCustomStoreDataProvider()
+    {
+        return [
+            ['description', '', 'not_empty_value', 'not_empty_value'],                  //0
+            ['description', '', '', null],                                              //1
+            ['description', '', null, 'Description with <b>html tag</b>'],              //2
+            ['description', '', false, 'Description with <b>html tag</b>'],             //3
+
+            ['description', 'not_empty_value', 'not_empty_value2', 'not_empty_value2'], //4
+            ['description', 'not_empty_value', '', null],                               //5
+            ['description', 'not_empty_value', null, 'Description with <b>html tag</b>'], //6
+            ['description', 'not_empty_value', false, 'Description with <b>html tag</b>'], //7
+
+            ['description', null, 'not_empty_value', 'not_empty_value'],                 //8
+            ['description', null, '', null],                                             //9
+            ['description', null, false, 'Description with <b>html tag</b>'],            //10
+
+            ['description', false, 'not_empty_value', 'not_empty_value'],                //11
+            ['description', false, '', null],                                            //12
+            ['description', false, null, 'Description with <b>html tag</b>'],            //13
+        ];
+    }
+
+    /**
+     * @return array
+     */
+    public function getCustomAttributeDataProvider()
+    {
+        return [
+            ['dropdown_attribute', 0, '', 1, 1],        //0
+            ['dropdown_attribute', 0, '', '', null],    //1
+            ['dropdown_attribute', 0, '', null, 0],     //2
+            ['dropdown_attribute', 0, '', false, 0],    //3
+
+            ['dropdown_attribute', 0, 1, 2, 2],         //4
+            ['dropdown_attribute', 0, 1, '', null],     //5
+            ['dropdown_attribute', 0, 1, null, 0],      //6
+            ['dropdown_attribute', 0, 1, false, 0],     //7
+
+            ['dropdown_attribute', 0, null, 1, 1],      //8
+            ['dropdown_attribute', 0, null, '', null],  //9
+            ['dropdown_attribute', 0, null, false, 0],  //10
+
+            ['dropdown_attribute', 0, false, 1, 1],     //11
+            ['dropdown_attribute', 0, false, '', null], //12
+            ['dropdown_attribute', 0, false, null, 0],  //13
+
+            ['dropdown_attribute', 0, '-', 1, 1],       //14
+            ['dropdown_attribute', 0, '-', '', null],   //15
+            ['dropdown_attribute', 0, '-', null, 0],    //16
+            ['dropdown_attribute', 0, '-', false, 0],   //17
+        ];
+    }
+}