Fixed suspicious usage of sizeof, rewrote function comments, implemented test for sceneHandler registration
diff --git a/src/app/clusters/scenes/ExtensionFieldsSetsImpl.cpp b/src/app/clusters/scenes/ExtensionFieldsSetsImpl.cpp
index 7c85bc7..3e9a223 100644
--- a/src/app/clusters/scenes/ExtensionFieldsSetsImpl.cpp
+++ b/src/app/clusters/scenes/ExtensionFieldsSetsImpl.cpp
@@ -129,7 +129,7 @@
     VerifyOrReturnError(position < kMaxClusterPerScenes, CHIP_ERROR_INVALID_ARGUMENT);
     VerifyOrReturnValue(!this->IsEmpty() && !this->mEFS[position].IsEmpty(), CHIP_NO_ERROR);
 
-    uint8_t nextPos = position++;
+    uint8_t nextPos = static_cast<uint8_t>(position + 1);
     uint8_t moveNum = static_cast<uint8_t>(kMaxClusterPerScenes - nextPos);
 
     // TODO: Implement general array management methods
diff --git a/src/app/clusters/scenes/SceneTable.h b/src/app/clusters/scenes/SceneTable.h
index 98c7548..be4688a 100644
--- a/src/app/clusters/scenes/SceneTable.h
+++ b/src/app/clusters/scenes/SceneTable.h
@@ -56,40 +56,52 @@
     SceneHandler(){};

     virtual ~SceneHandler() = default;

 

+    /// @brief Gets the list of supported clusters for an endpoint

+    /// @param endpoint target endpoint

+    /// @param clusterBuffer Buffer to hold the supported cluster IDs, cannot hold more than

+    /// CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENES

+    virtual void GetSupportedClusters(EndpointId endpoint, Span<ClusterId> & clusterBuffer) = 0;

+

+    /// @brief Returns whether or not a cluster is supported on an endpoint

+    /// @param endpoint Target Endpoint ID

+    /// @param cluster Target Cluster ID

+    /// @return true if supported, false if not supported

     virtual bool SupportsCluster(EndpointId endpoint, ClusterId cluster) = 0;

 

     /// @brief From command AddScene, allows handler to filter through clusters in command to serialize only the supported ones.

     /// @param endpoint Endpoint ID

     /// @param cluster  Cluster ID to fetch from command

-    /// @param serialysedBytes Buffer for ExtensionFieldSet in command

+    /// @param serialisedBytes Buffer for ExtensionFieldSet in command

     /// @param extensionFieldSet ExtensionFieldSets provided by the AddScene Command

-    /// @return

-    virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, ClusterId & cluster, MutableByteSpan & serialysedBytes,

+    /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise

+    virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, ClusterId & cluster, MutableByteSpan & serialisedBytes,

                                     app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet) = 0;

 

-    /// @brief From command SaveScene, retrieves ExtensionField from nvm

-    /// @param endpoint

-    /// @param cluster

-    /// @param serialysedBytes

-    /// @return

-    virtual CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialysedBytes) = 0;

+    /// @brief From command StoreScene, retrieves ExtensionField from nvm, it is the functions responsability to resize the mutable

+    /// span if necessary, a number of byte equal to the span will be stored in memory

+    /// @param endpoint Target Endpoint

+    /// @param cluster Target Cluster

+    /// @param serialisedBytes Output buffer, data needs to be writen in there and size adjusted if smaller than

+    /// kMaxFieldsPerCluster

+    /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise

+    virtual CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialisedBytes) = 0;

 

     /// @brief From stored scene (e.g. ViewScene), deserialize ExtensionFieldSet into a command object

     /// @param endpoint Endpoint ID

-    /// @param cluster Cluster ID to set in command

-    /// @param serialysedBytes ExtensionFieldSet stored in NVM

+    /// @param cluster Cluster ID to save

+    /// @param serialisedBytes ExtensionFieldSet stored in NVM

     /// @param extensionFieldSet ExtensionFieldSet in command format

-    /// @return

-    virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, ByteSpan & serialysedBytes,

+    /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise

+    virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, ByteSpan & serialisedBytes,

                                    app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) = 0;

 

     /// @brief From stored scene (e.g RecallScene), applies EFS values to cluster at transition time

     /// @param endpoint Endpoint ID

     /// @param cluster Cluster ID

-    /// @param serialysedBytes ExtensionFieldSet stored in NVM

+    /// @param serialisedBytes ExtensionFieldSet stored in NVM

     /// @param timeMs Transition time in ms to apply the scene

-    /// @return

-    virtual CHIP_ERROR ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialysedBytes, TransitionTimeMs timeMs) = 0;

+    /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise

+    virtual CHIP_ERROR ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialisedBytes, TransitionTimeMs timeMs) = 0;

 };

 

 class SceneTable

@@ -318,21 +330,50 @@
     virtual CHIP_ERROR RemoveSceneTableEntry(FabricIndex fabric_index, SceneStorageId scene_id)                       = 0;

     virtual CHIP_ERROR RemoveSceneTableEntryAtPosition(FabricIndex fabric_index, SceneIndex scened_idx)               = 0;

 

+    // SceneHandlers

+    virtual CHIP_ERROR RegisterHandler(SceneHandler * handler) = 0;

+    virtual CHIP_ERROR UnregisterHandler(uint8_t position)     = 0;

+

+    // Extension field sets operation

+    virtual CHIP_ERROR SceneSaveEFS(SceneTableEntry & scene)                                    = 0;

+    virtual CHIP_ERROR SceneApplyEFS(FabricIndex fabric_index, const SceneStorageId & scene_id) = 0;

+

+    // Fabrics

+    virtual CHIP_ERROR RemoveFabric(FabricIndex fabric_index) = 0;

+

     // Iterators

     using SceneEntryIterator = CommonIterator<SceneTableEntry>;

 

     virtual SceneEntryIterator * IterateSceneEntry(FabricIndex fabric_index) = 0;

 

-    // Fabrics

-    virtual CHIP_ERROR RemoveFabric(FabricIndex fabric_index) = 0;

-

     // Handlers

-    SceneHandler * mHandlers[CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENES] = { nullptr };

-    uint8_t handlerNum                                                   = 0;

+    virtual bool HandlerListEmpty() { return (handlerNum == 0); }

+    virtual bool HandlerListFull() { return (handlerNum >= kMaxSceneHandlers); }

+    virtual uint8_t GetHandlerNum() { return this->handlerNum; }

 

-protected:

-    const uint8_t mMaxScenePerFabric = kMaxScenePerFabric;

+    SceneHandler * mHandlers[kMaxSceneHandlers] = { nullptr };

+    uint8_t handlerNum                          = 0;

 };

 

+/**

+ * Instance getter for the global SceneTable.

+ *

+ * Callers have to externally synchronize usage of this function.

+ *

+ * @return The global Scene Table

+ */

+SceneTable * GetSceneTable();

+

+/**

+ * Instance setter for the global Scene Table.

+ *

+ * Callers have to externally synchronize usage of this function.

+ *

+ * The `provider` can be set to nullptr if the owner is done with it fully.

+ *

+ * @param[in] provider pointer to the Scene Table global instance to use

+ */

+void SetSceneTable(SceneTable * provider);

+

 } // namespace scenes

 } // namespace chip

diff --git a/src/app/clusters/scenes/SceneTableImpl.cpp b/src/app/clusters/scenes/SceneTableImpl.cpp
index 0c4ac6b..df68536 100644
--- a/src/app/clusters/scenes/SceneTableImpl.cpp
+++ b/src/app/clusters/scenes/SceneTableImpl.cpp
@@ -443,12 +443,12 @@
     VerifyOrReturnError(position < kMaxSceneHandlers, CHIP_ERROR_INVALID_ARGUMENT);
     VerifyOrReturnValue(!this->HandlerListEmpty() && !(this->mHandlers[position] == nullptr), CHIP_NO_ERROR);
 
-    uint8_t nextPos = position++;
+    uint8_t nextPos = static_cast<uint8_t>(position + 1);
     uint8_t moveNum = static_cast<uint8_t>(kMaxSceneHandlers - nextPos);
 
     // TODO: Implement general array management methods
     // Compress array after removal
-    memmove(&this->mHandlers[position], &this->mHandlers[nextPos], sizeof(SceneHandler *) * moveNum);
+    memmove(&this->mHandlers[position], &this->mHandlers[nextPos], sizeof(this->mHandlers[position]) * moveNum);
 
     this->handlerNum--;
     // Clear last occupied position
@@ -457,20 +457,27 @@
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR DefaultSceneTableImpl::SceneSaveEFS(SceneTableEntry & scene, clusterId cluster)
+CHIP_ERROR DefaultSceneTableImpl::SceneSaveEFS(SceneTableEntry & scene)
 {
-    ExtensionFieldsSet EFS;
-    MutableByteSpan EFSSpan = MutableByteSpan(EFS.mBytesBuffer, kMaxFieldsPerCluster);
     if (!this->HandlerListEmpty())
     {
         for (uint8_t i = 0; i < this->handlerNum; i++)
         {
+            clusterId cArray[kMaxClusterPerScenes];
+            Span<clusterId> cSpan(cArray);
             if (this->mHandlers[i] != nullptr)
             {
-                EFS.mID = cluster;
-                ReturnErrorOnFailure(this->mHandlers[i]->SerializeSave(scene.mStorageId.mEndpointId, cluster, EFSSpan));
-                EFS.mUsedBytes = (uint8_t) EFSSpan.size();
-                ReturnErrorOnFailure(scene.mStorageData.mExtensionFieldsSets.InsertFieldSet(EFS));
+                this->mHandlers[i]->GetSupportedClusters(scene.mStorageId.mEndpointId, cSpan);
+                for (uint8_t j = 0; j < cSpan.size(); j++)
+                {
+                    ExtensionFieldsSet EFS;
+                    MutableByteSpan EFSSpan = MutableByteSpan(EFS.mBytesBuffer, kMaxFieldsPerCluster);
+
+                    EFS.mID = cArray[j];
+                    ReturnErrorOnFailure(this->mHandlers[i]->SerializeSave(scene.mStorageId.mEndpointId, EFS.mID, EFSSpan));
+                    EFS.mUsedBytes = (uint8_t) EFSSpan.size();
+                    ReturnErrorOnFailure(scene.mStorageData.mExtensionFieldsSets.InsertFieldSet(EFS));
+                }
             }
         }
     }
@@ -585,16 +592,16 @@
 
 namespace {
 
-DefaultSceneTableImpl * gSceneTable = nullptr;
+SceneTable * gSceneTable = nullptr;
 
 } // namespace
 
-DefaultSceneTableImpl * GetSceneTable()
+SceneTable * GetSceneTable()
 {
     return gSceneTable;
 }
 
-void SetSceneTable(DefaultSceneTableImpl * provider)
+void SetSceneTable(SceneTable * provider)
 {
     gSceneTable = provider;
 }
diff --git a/src/app/clusters/scenes/SceneTableImpl.h b/src/app/clusters/scenes/SceneTableImpl.h
index aac4787..4257677 100644
--- a/src/app/clusters/scenes/SceneTableImpl.h
+++ b/src/app/clusters/scenes/SceneTableImpl.h
@@ -44,10 +44,10 @@
     /// @brief Function to serialize data from an add scene command, assume the incoming extensionFieldSet is initialized
     /// @param endpoint Target Endpoint
     /// @param cluster Cluster in the Extension field set, filled by the function
-    /// @param serialyzedBytes Mutable Byte span to hold EFS data from command
+    /// @param serialisedBytes Mutable Byte span to hold EFS data from command
     /// @param extensionFieldSet Extension field set from commmand, pre initialized
     /// @return CHIP_NO_ERROR if success, specific CHIP_ERROR otherwise
-    virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, ClusterId & cluster, MutableByteSpan & serialyzedBytes,
+    virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, ClusterId & cluster, MutableByteSpan & serialisedBytes,
                                     app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet) override
     {
         app::DataModel::List<app::Clusters::Scenes::Structs::AttributeValuePair::Type> attributeValueList;
@@ -88,7 +88,7 @@
         attributeValueList = mAVPairs;
         attributeValueList.reduce_size(pairCount);
 
-        writer.Init(serialyzedBytes);
+        writer.Init(serialisedBytes);
         ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
         ReturnErrorOnFailure(app::DataModel::Encode(
             writer, TLV::ContextTag(to_underlying(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList)),
@@ -101,9 +101,9 @@
     /// @brief Simulates taking data from nvm and loading it in a command object if the cluster is supported by the endpoint
     /// @param endpoint target endpoint
     /// @param cluster  target cluster
-    /// @param serialyzedBytes data to deserialize into EFS
+    /// @param serialisedBytes data to deserialize into EFS
     /// @return CHIP_NO_ERROR if Extension Field Set was successfully populated, specific CHIP_ERROR otherwise
-    virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, ByteSpan & serialyzedBytes,
+    virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, ByteSpan & serialisedBytes,
                                    app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) override
     {
         app::DataModel::DecodableList<app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType> attributeValueList;
@@ -117,7 +117,7 @@
         VerifyOrReturnError(SupportsCluster(endpoint, cluster), CHIP_ERROR_INVALID_ARGUMENT);
 
         extensionFieldSet.clusterID = cluster;
-        reader.Init(serialyzedBytes);
+        reader.Init(serialisedBytes);
         ReturnErrorOnFailure(reader.Next());
         ReturnErrorOnFailure(reader.EnterContainer(outer));
         ReturnErrorOnFailure(reader.Next());
@@ -183,12 +183,12 @@
     CHIP_ERROR RemoveSceneTableEntryAtPosition(FabricIndex fabric_index, SceneIndex scened_idx) override;
 
     // SceneHandlers
-    CHIP_ERROR RegisterHandler(SceneHandler * handler);
-    CHIP_ERROR UnregisterHandler(uint8_t position);
+    CHIP_ERROR RegisterHandler(SceneHandler * handler) override;
+    CHIP_ERROR UnregisterHandler(uint8_t position) override;
 
     // Extension field sets operation
-    CHIP_ERROR SceneSaveEFS(SceneTableEntry & scene, clusterId cluster);
-    CHIP_ERROR SceneApplyEFS(FabricIndex fabric_index, const SceneStorageId & scene_id);
+    CHIP_ERROR SceneSaveEFS(SceneTableEntry & scene) override;
+    CHIP_ERROR SceneApplyEFS(FabricIndex fabric_index, const SceneStorageId & scene_id) override;
 
     // Fabrics
     CHIP_ERROR RemoveFabric(FabricIndex fabric_index) override;
@@ -196,10 +196,6 @@
     // Iterators
     SceneEntryIterator * IterateSceneEntry(FabricIndex fabric_index) override;
 
-    bool HandlerListEmpty() { return (handlerNum == 0); }
-    bool HandlerListFull() { return (handlerNum >= CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENES); }
-    uint8_t GetHandlerNum() { return this->handlerNum; }
-
 protected:
     class SceneEntryIteratorImpl : public SceneEntryIterator
     {
@@ -222,24 +218,5 @@
     ObjectPool<SceneEntryIteratorImpl, kIteratorsMax> mSceneEntryIterators;
 }; // class DefaultSceneTableImpl
 
-/**
- * Instance getter for the global SceneTable.
- *
- * Callers have to externally synchronize usage of this function.
- *
- * @return The global Scene Table
- */
-DefaultSceneTableImpl * GetSceneTable();
-
-/**
- * Instance setter for the global Scene Table.
- *
- * Callers have to externally synchronize usage of this function.
- *
- * The `provider` can be set to nullptr if the owner is done with it fully.
- *
- * @param[in] provider pointer to the Scene Table global instance to use
- */
-void SetSceneTable(DefaultSceneTableImpl * provider);
 } // namespace scenes
 } // namespace chip
diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp
index 527fb34..4f0813f 100644
--- a/src/app/tests/TestSceneTable.cpp
+++ b/src/app/tests/TestSceneTable.cpp
@@ -24,6 +24,8 @@
 #include <nlunit-test.h>
 
 using namespace chip;
+
+using SceneTable         = scenes::SceneTable;
 using SceneTableEntry    = scenes::DefaultSceneTableImpl::SceneTableEntry;
 using SceneTableImpl     = scenes::DefaultSceneTableImpl;
 using SceneStorageId     = scenes::DefaultSceneTableImpl::SceneStorageId;
@@ -119,6 +121,24 @@
     TestSceneHandler() = default;
     ~TestSceneHandler() override {}
 
+    // Fills in cluster buffer and adjusts its size to lower than the maximum number of cluster per scenes
+    virtual void GetSupportedClusters(EndpointId endpoint, Span<ClusterId> & clusterBuffer) override
+    {
+        ClusterId * buffer = clusterBuffer.data();
+        if (endpoint == TEST_ENDPOINT1)
+        {
+            buffer[0] = ON_OFF_CID;
+            buffer[1] = LV_CTR_CID;
+            clusterBuffer.reduce_size(2);
+        }
+        else if (endpoint == TEST_ENDPOINT2)
+        {
+            buffer[0] = ON_OFF_CID;
+            buffer[1] = CC_CTR_CID;
+            clusterBuffer.reduce_size(2);
+        }
+    }
+
     // Default function only checks if endpoint and clusters are valid
     bool SupportsCluster(EndpointId endpoint, ClusterId cluster) override
     {
@@ -145,9 +165,9 @@
     /// @brief Simulates save from cluster, data is already in an EFS struct but this isn't mandatory
     /// @param endpoint target endpoint
     /// @param cluster  target cluster
-    /// @param serialyzedBytes data to serialize into EFS
+    /// @param serialisedBytes data to serialize into EFS
     /// @return success if successfully serialized the data, CHIP_ERROR_INVALID_ARGUMENT if endpoint or cluster not supported
-    CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialyzedBytes) override
+    CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialisedBytes) override
     {
         CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
 
@@ -157,13 +177,13 @@
             {
             case ON_OFF_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(15); // Used memory for OnOff TLV
+                memcpy(serialisedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(15); // Used memory for OnOff TLV
                 break;
             case LV_CTR_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), LC_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(27); // Used memory for Level Control TLV
+                memcpy(serialisedBytes.data(), LC_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(27); // Used memory for Level Control TLV
                 break;
             default:
                 break;
@@ -175,13 +195,13 @@
             {
             case ON_OFF_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(15); // Used memory for Color Control TLV
+                memcpy(serialisedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(15); // Used memory for OnOff TLV
                 break;
             case CC_CTR_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), CC_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(99); // Used memory for Color Control TLV
+                memcpy(serialisedBytes.data(), CC_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(99); // Used memory for Color Control TLV
                 break;
             default:
                 break;
@@ -194,11 +214,11 @@
     /// "cluster"
     /// @param endpoint target endpoint
     /// @param cluster  target cluster
-    /// @param serialyzedBytes Data from nvm
+    /// @param serialisedBytes Data from nvm
     /// @param timeMs transition time in ms
     /// @return CHIP_NO_ERROR if value as expected, CHIP_ERROR_INVALID_ARGUMENT otherwise
     CHIP_ERROR
-    ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialyzedBytes, TransitionTimeMs timeMs) override
+    ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialisedBytes, TransitionTimeMs timeMs) override
     {
         CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
 
@@ -208,13 +228,13 @@
             switch (cluster)
             {
             case ON_OFF_CID:
-                if (!memcmp(serialyzedBytes.data(), OO_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), OO_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
                 break;
             case LV_CTR_CID:
-                if (!memcmp(serialyzedBytes.data(), LC_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), LC_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
@@ -230,13 +250,13 @@
             switch (cluster)
             {
             case ON_OFF_CID:
-                if (!memcmp(serialyzedBytes.data(), OO_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), OO_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
                 break;
             case CC_CTR_CID:
-                if (!memcmp(serialyzedBytes.data(), CC_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), CC_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
@@ -254,16 +274,61 @@
 static SceneTableImpl sSceneTable;
 static TestSceneHandler sHandler;
 
-void ResetSceneTable(SceneTableImpl * sceneTable)
+void ResetSceneTable(SceneTable * sceneTable)
 {
     sceneTable->RemoveFabric(kFabric1);
     sceneTable->RemoveFabric(kFabric2);
 }
 
+void TestHandlerRegistration(nlTestSuite * aSuite, void * aContext)
+{
+    SceneTable * sceneTable = scenes::GetSceneTable();
+    TestSceneHandler tmpHandler[scenes::kMaxSceneHandlers];
+
+    for (uint8_t i = 0; i < scenes::kMaxSceneHandlers; i++)
+    {
+        NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == i);
+        NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->RegisterHandler(&tmpHandler[i]));
+    }
+
+    NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == scenes::kMaxSceneHandlers);
+    // Removal at begining
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->UnregisterHandler(0));
+    NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == static_cast<uint8_t>(scenes::kMaxSceneHandlers - 1));
+    // Confirm array was compressed and last position is now null
+    NL_TEST_ASSERT(aSuite, nullptr == sceneTable->mHandlers[scenes::kMaxSceneHandlers - 1]);
+
+    // Removal at the middle
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->UnregisterHandler(3));
+    NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == static_cast<uint8_t>(scenes::kMaxSceneHandlers - 2));
+    // Confirm array was compressed and last position is now null
+    NL_TEST_ASSERT(aSuite, nullptr == sceneTable->mHandlers[scenes::kMaxSceneHandlers - 2]);
+
+    // Removal at the middle
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->UnregisterHandler(scenes::kMaxSceneHandlers - 3));
+    NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == static_cast<uint8_t>(scenes::kMaxSceneHandlers - 3));
+    NL_TEST_ASSERT(aSuite, nullptr == sceneTable->mHandlers[scenes::kMaxSceneHandlers - 3]);
+
+    // Emptying Handler array
+    for (uint8_t i = 0; i < scenes::kMaxSceneHandlers; i++)
+    {
+        NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->UnregisterHandler(0));
+    }
+
+    // Verify the handler num has been updated properly
+    NL_TEST_ASSERT(aSuite, sceneTable->handlerNum == 0);
+
+    // Verify all array is empty
+    for (uint8_t i = 0; i < scenes::kMaxSceneHandlers; i++)
+    {
+        NL_TEST_ASSERT(aSuite, nullptr == sceneTable->mHandlers[i]);
+    }
+}
+
 void TestHandlerFunctions(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
-    ClusterId tempCluster       = 0;
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
+    ClusterId tempCluster   = 0;
 
     app::Clusters::Scenes::Structs::ExtensionFieldSet::Type extensionFieldSetOut;
     app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType extensionFieldSetIn;
@@ -409,7 +474,7 @@
     // Verify Deserializing is properly filling out output extension field set for on off
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sHandler.Deserialize(TEST_ENDPOINT1, ON_OFF_CID, OO_list, extensionFieldSetOut));
 
-    // Verify Encoding the Extension field set returns the same data as
+    // Verify Encoding the Extension field set returns the same data as the one serialized for on off previously
     writer.Init(buff_span);
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
     NL_TEST_ASSERT(aSuite,
@@ -425,7 +490,7 @@
     // Verify Deserializing is properly filling out output extension field set for level control
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sHandler.Deserialize(TEST_ENDPOINT1, LV_CTR_CID, LC_list, extensionFieldSetOut));
 
-    // Verify Encoding the Extension field set returns the same data as
+    // Verify Encoding the Extension field set returns the same data as the one serialized for level control previously
     writer.Init(buff_span);
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
     NL_TEST_ASSERT(aSuite,
@@ -441,7 +506,7 @@
     // Verify Deserializing is properly filling out output extension field set for color control
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sHandler.Deserialize(TEST_ENDPOINT2, CC_CTR_CID, CC_list, extensionFieldSetOut));
 
-    // Verify Encoding the Extension field set returns the same data as
+    // Verify Encoding the Extension field set returns the same data as the one serialized for color control previously
     writer.Init(buff_span);
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
     NL_TEST_ASSERT(aSuite,
@@ -457,31 +522,23 @@
 
 void TestStoreScenes(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     NL_TEST_ASSERT(aSuite, sceneTable);
 
     // Reset test
     ResetSceneTable(sceneTable);
 
     // Populate scene1's EFS (Endpoint1)
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene1, ON_OFF_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene1, LV_CTR_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == sceneTable->SceneSaveEFS(scene1, CC_CTR_CID));
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene1));
 
     // Populate scene2's EFS (Endpoint1)
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene2, ON_OFF_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene2, LV_CTR_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == sceneTable->SceneSaveEFS(scene2, CC_CTR_CID));
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene2));
 
     // Populate scene3's EFS (Endpoint2)
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene3, ON_OFF_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == sceneTable->SceneSaveEFS(scene3, LV_CTR_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene3, CC_CTR_CID));
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene3));
 
     // Populate scene3's EFS (Endpoint2)
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene4, ON_OFF_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == sceneTable->SceneSaveEFS(scene4, LV_CTR_CID));
-    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene4, CC_CTR_CID));
+    NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SceneSaveEFS(scene4));
 
     SceneTableEntry scene;
 
@@ -495,7 +552,7 @@
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene7));
     NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene8));
 
-    // Too many scenes 1 fabric
+    // Too many scenes for 1 fabric
     NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_LIST_LENGTH == sceneTable->SetSceneTableEntry(kFabric1, scene9));
 
     // Not Found
@@ -530,7 +587,7 @@
 
 void TestOverwriteScenes(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     NL_TEST_ASSERT(aSuite, sceneTable);
 
     SceneTableEntry scene;
@@ -554,7 +611,7 @@
 
 void TestIterateScenes(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     NL_TEST_ASSERT(aSuite, sceneTable);
 
     SceneTableEntry scene;
@@ -590,7 +647,7 @@
 
 void TestRemoveScenes(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     NL_TEST_ASSERT(aSuite, sceneTable);
 
     SceneTableEntry scene;
@@ -681,7 +738,7 @@
 
 void TestFabricScenes(nlTestSuite * aSuite, void * aContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     NL_TEST_ASSERT(aSuite, sceneTable);
 
     // Reset test
@@ -757,7 +814,7 @@
  */
 int TestTeardown(void * inContext)
 {
-    SceneTableImpl * sceneTable = chip::scenes::GetSceneTable();
+    SceneTable * sceneTable = chip::scenes::GetSceneTable();
     if (nullptr != sceneTable)
     {
         sceneTable->Finish();
@@ -767,12 +824,14 @@
 }
 int TestSceneTable()
 {
-    static nlTest sTests[] = { NL_TEST_DEF("TestStoreScenes", TestHandlerFunctions),
+    static nlTest sTests[] = { NL_TEST_DEF("TestHandlerRegistration", TestHandlerRegistration),
+                               NL_TEST_DEF("TestHandlerFunctions", TestHandlerFunctions),
                                NL_TEST_DEF("TestStoreScenes", TestStoreScenes),
                                NL_TEST_DEF("TestOverwriteScenes", TestOverwriteScenes),
                                NL_TEST_DEF("TestIterateScenes", TestIterateScenes),
                                NL_TEST_DEF("TestRemoveScenes", TestRemoveScenes),
                                NL_TEST_DEF("TestFabricScenes", TestFabricScenes),
+
                                NL_TEST_SENTINEL() };
 
     nlTestSuite theSuite = {
diff --git a/src/lib/support/TestSceneTable.h b/src/lib/support/TestSceneTable.h
index a8706ea..26bfb84 100644
--- a/src/lib/support/TestSceneTable.h
+++ b/src/lib/support/TestSceneTable.h
@@ -26,6 +26,7 @@
 
 using FabricIndex        = chip::FabricIndex;
 using SceneTableEntry    = chip::scenes::DefaultSceneTableImpl::SceneTableEntry;
+using SceneTable         = chip::scenes::SceneTable;
 using SceneTableImpl     = chip::scenes::DefaultSceneTableImpl;
 using SceneStorageId     = chip::scenes::DefaultSceneTableImpl::SceneStorageId;
 using SceneData          = chip::scenes::DefaultSceneTableImpl::SceneData;
@@ -72,12 +73,27 @@
 class TestSceneHandler : public scenes::DefaultSceneHandlerImpl
 {
 public:
-    static constexpr uint8_t kMaxValueSize = 4;
-    static constexpr uint8_t kMaxAvPair    = 15;
-
     TestSceneHandler() = default;
     ~TestSceneHandler() override {}
 
+    // Fills in cluster buffer and adjusts its size to lower than the maximum number of cluster per scenes
+    virtual void GetSupportedClusters(EndpointId endpoint, Span<ClusterId> & clusterBuffer) override
+    {
+        ClusterId * buffer = clusterBuffer.data();
+        if (endpoint == TEST_ENDPOINT1)
+        {
+            buffer[0] = ON_OFF_CID;
+            buffer[1] = LV_CTR_CID;
+            clusterBuffer.reduce_size(2);
+        }
+        else if (endpoint == TEST_ENDPOINT2)
+        {
+            buffer[0] = ON_OFF_CID;
+            buffer[1] = CC_CTR_CID;
+            clusterBuffer.reduce_size(2);
+        }
+    }
+
     // Default function only checks if endpoint and clusters are valid
     bool SupportsCluster(EndpointId endpoint, ClusterId cluster) override
     {
@@ -104,9 +120,9 @@
     /// @brief Simulates save from cluster, data is already in an EFS struct but this isn't mandatory
     /// @param endpoint target endpoint
     /// @param cluster  target cluster
-    /// @param serialyzedBytes data to serialize into EFS
+    /// @param serialisedBytes data to serialize into EFS
     /// @return success if successfully serialized the data, CHIP_ERROR_INVALID_ARGUMENT if endpoint or cluster not supported
-    CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialyzedBytes) override
+    CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serialisedBytes) override
     {
         CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
 
@@ -116,13 +132,13 @@
             {
             case ON_OFF_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(15); // Used memory for OnOff TLV
+                memcpy(serialisedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(15); // Used memory for OnOff TLV
                 break;
             case LV_CTR_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), LC_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(27); // Used memory for Level Control TLV
+                memcpy(serialisedBytes.data(), LC_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(27); // Used memory for Level Control TLV
                 break;
             default:
                 break;
@@ -134,13 +150,13 @@
             {
             case ON_OFF_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(15); // Used memory for Color Control TLV
+                memcpy(serialisedBytes.data(), OO_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(15); // Used memory for OnOff TLV
                 break;
             case CC_CTR_CID:
                 err = CHIP_NO_ERROR;
-                memcpy(serialyzedBytes.data(), CC_buffer, scenes::kMaxFieldsPerCluster);
-                serialyzedBytes.reduce_size(99); // Used memory for Color Control TLV
+                memcpy(serialisedBytes.data(), CC_buffer, scenes::kMaxFieldsPerCluster);
+                serialisedBytes.reduce_size(99); // Used memory for Color Control TLV
                 break;
             default:
                 break;
@@ -153,11 +169,11 @@
     /// "cluster"
     /// @param endpoint target endpoint
     /// @param cluster  target cluster
-    /// @param serialyzedBytes Data from nvm
+    /// @param serialisedBytes Data from nvm
     /// @param timeMs transition time in ms
     /// @return CHIP_NO_ERROR if value as expected, CHIP_ERROR_INVALID_ARGUMENT otherwise
     CHIP_ERROR
-    ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialyzedBytes, TransitionTimeMs timeMs) override
+    ApplyScene(EndpointId endpoint, ClusterId cluster, ByteSpan & serialisedBytes, TransitionTimeMs timeMs) override
     {
         CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
 
@@ -167,13 +183,13 @@
             switch (cluster)
             {
             case ON_OFF_CID:
-                if (!memcmp(serialyzedBytes.data(), OO_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), OO_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
                 break;
             case LV_CTR_CID:
-                if (!memcmp(serialyzedBytes.data(), LC_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), LC_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
@@ -189,13 +205,13 @@
             switch (cluster)
             {
             case ON_OFF_CID:
-                if (!memcmp(serialyzedBytes.data(), OO_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), OO_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
                 break;
             case CC_CTR_CID:
-                if (!memcmp(serialyzedBytes.data(), CC_buffer, serialyzedBytes.size()))
+                if (!memcmp(serialisedBytes.data(), CC_buffer, serialisedBytes.size()))
                 {
                     err = CHIP_NO_ERROR;
                 }
@@ -211,7 +227,7 @@
 
 static TestSceneHandler sHandler;
 
-CHIP_ERROR scene_handler_test(SceneTableImpl * provider)
+CHIP_ERROR scene_handler_test(SceneTable * provider)
 {
     ClusterId tempCluster = 0;
 
@@ -387,7 +403,7 @@
     return CHIP_NO_ERROR;
 };
 
-CHIP_ERROR scene_store_test(SceneTableImpl * provider, FabricIndex fabric_index, SceneTableEntry & entry)
+CHIP_ERROR scene_store_test(SceneTable * provider, FabricIndex fabric_index, SceneTableEntry & entry)
 {
     SceneTableEntry temp;
 
@@ -400,7 +416,7 @@
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR scene_iterator_test(SceneTableImpl * provider, FabricIndex fabric_index, const SceneTableEntry & entry1,
+CHIP_ERROR scene_iterator_test(SceneTable * provider, FabricIndex fabric_index, const SceneTableEntry & entry1,
                                const SceneTableEntry & entry2, const SceneTableEntry & entry3)
 {
     SceneTableEntry temp;
@@ -428,8 +444,8 @@
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR scene_remove_test(SceneTableImpl * provider, FabricIndex fabric_index, SceneTableEntry & entry1,
-                             SceneTableEntry & entry2, SceneTableEntry & entry3)
+CHIP_ERROR scene_remove_test(SceneTable * provider, FabricIndex fabric_index, SceneTableEntry & entry1, SceneTableEntry & entry2,
+                             SceneTableEntry & entry3)
 {
     SceneTableEntry temp;
 
@@ -458,7 +474,7 @@
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR TestSceneData(SceneTableImpl * provider, FabricIndex fabric_index)
+CHIP_ERROR TestSceneData(SceneTable * provider, FabricIndex fabric_index)
 {
     CHIP_ERROR err = CHIP_NO_ERROR;
     // Scene storage ID
@@ -476,16 +492,13 @@
     SceneTableEntry scene2(sceneId2, sceneData2);
     SceneTableEntry scene3(sceneId3, sceneData3);
 
-    LogErrorOnFailure(scene_handler_test(provider));
-
-    err = provider->SceneSaveEFS(scene1, ON_OFF_CID);
-    LogErrorOnFailure(err);
-    err = provider->SceneSaveEFS(scene1, LV_CTR_CID);
+    err = scene_handler_test(provider);
     LogErrorOnFailure(err);
 
-    err = provider->SceneSaveEFS(scene3, ON_OFF_CID);
+    err = provider->SceneSaveEFS(scene1);
     LogErrorOnFailure(err);
-    err = provider->SceneSaveEFS(scene3, CC_CTR_CID);
+
+    err = provider->SceneSaveEFS(scene3);
     LogErrorOnFailure(err);
 
     // Tests