Update Darwin CHIPDevice data object format (#16049)

* CHIPAttributePath object and CHIPCommandPath object are used for paths
  instead of individual dictionary keys for path elements.
* NSError object replaces implementation specific status value.
* List TLV conversion code was removed.
* Implementation specific tag is replaced with context tag number just
  for Structure TLV.
* 64 bit int conversion was fixed.
* new operator was replaced with Platform::New.
* Float and double TLV decoding was fixed to distinguish them.
* Potential buffer overrun during UTF8String TLV conversion was fixed.
* String constant names were corrected.
* Method header comments were corrected.
diff --git a/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m b/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m
index 4f47df6..0ddb2c8 100644
--- a/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m
+++ b/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m
@@ -70,6 +70,12 @@
     return mConnectedDevice;
 }
 
+#ifdef DEBUG
+@interface CHIPDevice (Test)
+- (void)failSubscribers:(dispatch_queue_t)clientQueue completion:(void (^)(void))completion;
+@end
+#endif
+
 @interface CHIPDeviceTestPairingDelegate : NSObject <CHIPDevicePairingDelegate>
 @property (nonatomic, strong) XCTestExpectation * expectation;
 @end
@@ -214,9 +220,9 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 29);
-                                         XCTAssertEqual([result[@"attributeId"] unsignedIntegerValue], 0);
-                                         XCTAssertTrue([result[@"endpointId"] isKindOfClass:[NSNumber class]]);
+                                         CHIPAttributePath * path = result[@"attributePath"];
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 29);
+                                         XCTAssertEqual([path.attribute unsignedIntegerValue], 0);
                                          XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
                                          XCTAssertTrue([result[@"data"][@"type"] isEqualToString:@"Array"]);
                                      }
@@ -256,10 +262,11 @@
                                       XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                       NSArray * resultArray = values;
                                       for (NSDictionary * result in resultArray) {
-                                          XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                          XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 8);
-                                          XCTAssertEqual([result[@"attributeId"] unsignedIntegerValue], 17);
-                                          XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
+                                          CHIPAttributePath * path = result[@"attributePath"];
+                                          XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                          XCTAssertEqual([path.cluster unsignedIntegerValue], 8);
+                                          XCTAssertEqual([path.attribute unsignedIntegerValue], 17);
+                                          XCTAssertNil(result[@"error"]);
                                       }
                                       XCTAssertEqual([resultArray count], 1);
                                   }
@@ -281,18 +288,13 @@
     CHIPDevice * device = GetConnectedDevice();
     dispatch_queue_t queue = dispatch_get_main_queue();
 
-    NSDictionary * fields = [NSDictionary
-        dictionaryWithObjectsAndKeys:@"Structure", @"type",
-        [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:0], @"tag",
-                                                [NSDictionary dictionaryWithObjectsAndKeys:@"UnsignedInteger", @"type",
-                                                              [NSNumber numberWithUnsignedInteger:0], @"value", nil],
-                                                @"value", nil],
-                 [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:1], @"tag",
-                               [NSDictionary dictionaryWithObjectsAndKeys:@"UnsignedInteger", @"type",
-                                             [NSNumber numberWithUnsignedInteger:10], @"value", nil],
-                               @"value", nil],
-                 nil],
-        @"value", nil];
+    NSDictionary * fields = @{
+        @"type" : @"Structure",
+        @"value" : @[
+            @{ @"contextTag" : @0, @"data" : @ { @"type" : @"UnsignedInteger", @"value" : @0 } },
+            @{ @"contextTag" : @1, @"data" : @ { @"type" : @"UnsignedInteger", @"value" : @10 } }
+        ]
+    };
     [device invokeCommandWithEndpointId:1
                               clusterId:8
                               commandId:4
@@ -307,10 +309,11 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 8);
-                                         XCTAssertEqual([result[@"commandId"] unsignedIntegerValue], 4);
-                                         XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 8);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 4);
+                                         XCTAssertNil(result[@"error"]);
                                      }
                                      XCTAssertEqual([resultArray count], 1);
                                  }
@@ -397,14 +400,15 @@
     XCTestExpectation * reportExpectation = [self expectationWithDescription:@"report received"];
     globalReportHandler = ^(id _Nullable value, NSError * _Nullable error) {
         XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
-        XCTAssertTrue([value isKindOfClass:[NSDictionary class]]);
-        NSDictionary * result = value;
-        XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-        XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-        XCTAssertEqual([result[@"attributeId"] unsignedIntegerValue], 0);
-        XCTAssertTrue([result[@"value"] isKindOfClass:[NSDictionary class]]);
-        XCTAssertTrue([result[@"value"][@"type"] isEqualToString:@"Boolean"]);
-        if ([result[@"value"][@"value"] boolValue] == YES) {
+        XCTAssertTrue([value isKindOfClass:[NSArray class]]);
+        NSDictionary * result = value[0];
+        CHIPAttributePath * path = result[@"attributePath"];
+        XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+        XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+        XCTAssertEqual([path.attribute unsignedIntegerValue], 0);
+        XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
+        XCTAssertTrue([result[@"data"][@"type"] isEqualToString:@"Boolean"]);
+        if ([result[@"data"][@"value"] boolValue] == YES) {
             [reportExpectation fulfill];
             globalReportHandler = nil;
         }
@@ -412,7 +416,7 @@
 
     // Send commands to trigger attribute change
     XCTestExpectation * commandExpectation = [self expectationWithDescription:@"command responded"];
-    NSDictionary * fields = [NSDictionary dictionaryWithObjectsAndKeys:@"Structure", @"type", [NSArray array], @"value", nil];
+    NSDictionary * fields = @{ @"type" : @"Structure", @"value" : [NSArray array] };
     [device invokeCommandWithEndpointId:1
                               clusterId:6
                               commandId:1
@@ -427,10 +431,11 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-                                         XCTAssertEqual([result[@"commandId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 1);
+                                         XCTAssertNil(result[@"error"]);
                                      }
                                      XCTAssertEqual([resultArray count], 1);
                                  }
@@ -445,14 +450,15 @@
     reportExpectation = [self expectationWithDescription:@"receive OnOff attribute report"];
     globalReportHandler = ^(id _Nullable value, NSError * _Nullable error) {
         XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
-        XCTAssertTrue([value isKindOfClass:[NSDictionary class]]);
-        NSDictionary * result = value;
-        XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-        XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-        XCTAssertEqual([result[@"attributeId"] unsignedIntegerValue], 0);
-        XCTAssertTrue([result[@"value"] isKindOfClass:[NSDictionary class]]);
-        XCTAssertTrue([result[@"value"][@"type"] isEqualToString:@"Boolean"]);
-        if ([result[@"value"][@"value"] boolValue] == NO) {
+        XCTAssertTrue([value isKindOfClass:[NSArray class]]);
+        NSDictionary * result = value[0];
+        CHIPAttributePath * path = result[@"attributePath"];
+        XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+        XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+        XCTAssertEqual([path.attribute unsignedIntegerValue], 0);
+        XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
+        XCTAssertTrue([result[@"data"][@"type"] isEqualToString:@"Boolean"]);
+        if ([result[@"data"][@"value"] boolValue] == NO) {
             [reportExpectation fulfill];
             globalReportHandler = nil;
         }
@@ -474,10 +480,11 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-                                         XCTAssertEqual([result[@"commandId"] unsignedIntegerValue], 0);
-                                         XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 0);
+                                         XCTAssertNil(result[@"error"]);
                                      }
                                      XCTAssertEqual([resultArray count], 1);
                                  }
@@ -485,6 +492,13 @@
 
     // Wait for report
     [self waitForExpectations:[NSArray arrayWithObject:reportExpectation] timeout:kTimeoutInSeconds];
+
+    expectation = [self expectationWithDescription:@"Report handler deregistered"];
+    [device deregisterReportHandlersWithClientQueue:queue
+                                         completion:^{
+                                             [expectation fulfill];
+                                         }];
+    [self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds];
 }
 #endif
 
@@ -664,8 +678,9 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 29);
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
+                                         CHIPAttributePath * path = result[@"attributePath"];
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 29);
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
                                          XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
                                      }
                                      XCTAssertTrue([resultArray count] > 0);
@@ -807,10 +822,11 @@
                              NSLog(@"Read attribute cache value: %@, error %@", values, error);
                              XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
                              XCTAssertEqual([values count], 1);
-                             XCTAssertEqual([values[0][@"endpointId"] unsignedShortValue], 1);
-                             XCTAssertEqual([values[0][@"clusterId"] unsignedLongValue], 6);
-                             XCTAssertEqual([values[0][@"attributeId"] unsignedLongValue], 0);
-                             XCTAssertEqual([values[0][@"status"] intValue], 0);
+                             CHIPAttributePath * path = values[0][@"attributePath"];
+                             XCTAssertEqual([path.endpoint unsignedShortValue], 1);
+                             XCTAssertEqual([path.cluster unsignedLongValue], 6);
+                             XCTAssertEqual([path.attribute unsignedLongValue], 0);
+                             XCTAssertNil(values[0][@"error"]);
                              XCTAssertTrue([values[0][@"data"][@"type"] isEqualToString:@"Boolean"]);
                              XCTAssertEqual([values[0][@"data"][@"value"] boolValue], NO);
                              [cacheExpectation fulfill];
@@ -830,9 +846,10 @@
                              XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
                              XCTAssertTrue([values count] > 0);
                              for (NSDictionary<NSString *, id> * value in values) {
-                                 XCTAssertEqual([value[@"clusterId"] unsignedLongValue], 6);
-                                 XCTAssertEqual([value[@"attributeId"] unsignedLongValue], 0);
-                                 XCTAssertEqual([value[@"status"] intValue], 0);
+                                 CHIPAttributePath * path = value[@"attributePath"];
+                                 XCTAssertEqual([path.cluster unsignedLongValue], 6);
+                                 XCTAssertEqual([path.attribute unsignedLongValue], 0);
+                                 XCTAssertNil(value[@"error"]);
                              }
                              [cacheExpectation fulfill];
                          }];
@@ -851,8 +868,9 @@
                              XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
                              XCTAssertTrue([values count] > 0);
                              for (NSDictionary<NSString *, id> * value in values) {
-                                 XCTAssertEqual([value[@"endpointId"] unsignedShortValue], 1);
-                                 XCTAssertEqual([value[@"attributeId"] unsignedLongValue], 0);
+                                 CHIPAttributePath * path = value[@"attributePath"];
+                                 XCTAssertEqual([path.endpoint unsignedShortValue], 1);
+                                 XCTAssertEqual([path.attribute unsignedLongValue], 0);
                              }
                              [cacheExpectation fulfill];
                          }];
@@ -871,9 +889,10 @@
                              XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
                              XCTAssertTrue([values count] > 0);
                              for (NSDictionary<NSString *, id> * value in values) {
-                                 XCTAssertEqual([value[@"endpointId"] unsignedShortValue], 1);
-                                 XCTAssertEqual([value[@"clusterId"] unsignedLongValue], 6);
-                                 XCTAssertEqual([value[@"status"] intValue], 0);
+                                 CHIPAttributePath * path = value[@"attributePath"];
+                                 XCTAssertEqual([path.endpoint unsignedShortValue], 1);
+                                 XCTAssertEqual([path.cluster unsignedLongValue], 6);
+                                 XCTAssertNil(value[@"error"]);
                              }
                              [cacheExpectation fulfill];
                          }];
@@ -895,9 +914,114 @@
     [self waitForExpectations:@[ cacheExpectation ] timeout:kTimeoutInSeconds];
 }
 
-// Report behavior is erratic on the accessory side at the moment.
-// Hence this test is enabled only for individual manual test.
+#ifdef DEBUG
+// Test an error to subscription
+- (void)test012_SubscriptionError
+{
 #if MANUAL_INDIVIDUAL_TEST
+    [self initStack];
+    [self waitForCommissionee];
+#endif
+    CHIPDevice * device = GetConnectedDevice();
+    dispatch_queue_t queue = dispatch_get_main_queue();
+    XCTestExpectation * deregisterExpectation = [self expectationWithDescription:@"Report handler deregistered"];
+    [device deregisterReportHandlersWithClientQueue:queue
+                                         completion:^{
+                                             [deregisterExpectation fulfill];
+                                         }];
+    [self waitForExpectations:@[ deregisterExpectation ] timeout:kTimeoutInSeconds];
+
+    // Subscribe
+    XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe OnOff attribute"];
+    [device subscribeAttributeWithEndpointId:1
+        clusterId:6
+        attributeId:0
+        minInterval:1
+        maxInterval:10
+        clientQueue:queue
+        reportHandler:^(id _Nullable values, NSError * _Nullable error) {
+            NSLog(@"report attribute: OnOff values: %@, error: %@", values, error);
+
+            if (globalReportHandler) {
+                __auto_type callback = globalReportHandler;
+                callback(values, error);
+            }
+        }
+        subscriptionEstablished:^{
+            NSLog(@"subscribe attribute: OnOff established");
+            [expectation fulfill];
+        }];
+
+    // Wait till establishment
+    [self waitForExpectations:[NSArray arrayWithObject:expectation] timeout:kTimeoutInSeconds];
+
+    // Set up expectation for report
+    XCTestExpectation * reportExpectation = [self expectationWithDescription:@"report received"];
+    globalReportHandler = ^(id _Nullable value, NSError * _Nullable error) {
+        XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
+        XCTAssertTrue([value isKindOfClass:[NSArray class]]);
+        NSDictionary * result = value[0];
+        CHIPAttributePath * path = result[@"attributePath"];
+        XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+        XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+        XCTAssertEqual([path.attribute unsignedIntegerValue], 0);
+        XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
+        XCTAssertTrue([result[@"data"][@"type"] isEqualToString:@"Boolean"]);
+        if ([result[@"data"][@"value"] boolValue] == YES) {
+            [reportExpectation fulfill];
+            globalReportHandler = nil;
+        }
+    };
+
+    // Send commands to trigger attribute change
+    XCTestExpectation * commandExpectation = [self expectationWithDescription:@"command responded"];
+    NSDictionary * fields = @{ @"type" : @"Structure", @"value" : [NSArray array] };
+    [device invokeCommandWithEndpointId:1
+                              clusterId:6
+                              commandId:1
+                          commandFields:fields
+                            clientQueue:queue
+                             completion:^(id _Nullable values, NSError * _Nullable error) {
+                                 NSLog(@"invoke command: On values: %@, error: %@", values, error);
+
+                                 XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
+
+                                 {
+                                     XCTAssertTrue([values isKindOfClass:[NSArray class]]);
+                                     NSArray * resultArray = values;
+                                     for (NSDictionary * result in resultArray) {
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 1);
+                                         XCTAssertNil(result[@"error"]);
+                                     }
+                                     XCTAssertEqual([resultArray count], 1);
+                                 }
+                                 [commandExpectation fulfill];
+                             }];
+    [self waitForExpectations:[NSArray arrayWithObject:commandExpectation] timeout:kTimeoutInSeconds];
+
+    // Wait for report
+    [self waitForExpectations:[NSArray arrayWithObject:reportExpectation] timeout:kTimeoutInSeconds];
+
+    // Trigger reader failure
+    XCTestExpectation * failureExpectation = [self expectationWithDescription:@"failed on purpose"];
+    [device failSubscribers:queue
+                 completion:^{
+                     [failureExpectation fulfill];
+                 }];
+    [self waitForExpectations:@[ failureExpectation ] timeout:kTimeoutInSeconds];
+
+    deregisterExpectation = [self expectationWithDescription:@"Report handler deregistered"];
+    [device deregisterReportHandlersWithClientQueue:queue
+                                         completion:^{
+                                             [deregisterExpectation fulfill];
+                                         }];
+    [self waitForExpectations:@[ deregisterExpectation ] timeout:kTimeoutInSeconds];
+}
+#endif
+
 - (void)test900_SubscribeAllAttributes
 {
 #if MANUAL_INDIVIDUAL_TEST
@@ -906,6 +1030,14 @@
 #endif
     CHIPDevice * device = GetConnectedDevice();
     dispatch_queue_t queue = dispatch_get_main_queue();
+    XCTestExpectation * cleanSubscriptionExpectation = [self expectationWithDescription:@"Previous subscriptions cleaned"];
+    NSLog(@"Deregistering report handlers...");
+    [device deregisterReportHandlersWithClientQueue:queue
+                                         completion:^{
+                                             NSLog(@"Report handlers deregistered");
+                                             [cleanSubscriptionExpectation fulfill];
+                                         }];
+    [self waitForExpectations:@[ cleanSubscriptionExpectation ] timeout:kTimeoutInSeconds];
 
     XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe OnOff attribute"];
     __block void (^reportHandler)(id _Nullable values, NSError * _Nullable error) = nil;
@@ -935,69 +1067,24 @@
 
     // Set up expectation for report
     __auto_type reportExpectation = [self expectationWithDescription:@"receive OnOff attribute report"];
-    reportHandler = ^(id _Nullable value, NSError * _Nullable error) {
+    reportHandler = ^(id _Nullable values, NSError * _Nullable error) {
         XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
-        XCTAssertTrue([value isKindOfClass:[NSDictionary class]]);
-        NSDictionary * result = value;
-        XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-        XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-        XCTAssertTrue([result[@"value"] isKindOfClass:[NSDictionary class]]);
+        XCTAssertTrue([values isKindOfClass:[NSArray class]]);
+        NSDictionary * result = values[0];
+        CHIPAttributePath * path = result[@"attributePath"];
+        XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+        XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+        XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
 
-        if ([result[@"attributeId"] unsignedIntegerValue] == 0 && [result[@"value"][@"value"] boolValue] == YES) {
+        if ([path.attribute unsignedIntegerValue] == 0 && [result[@"data"][@"value"] boolValue] == YES) {
             [reportExpectation fulfill];
             reportHandler = nil;
         }
     };
 
-    // Send commands to trigger attribute change
+    // Send commands to set attribute state to a known state
     XCTestExpectation * commandExpectation = [self expectationWithDescription:@"command responded"];
-    NSDictionary * fields = [NSDictionary dictionaryWithObjectsAndKeys:@"Structure", @"type", [NSArray array], @"value", nil];
-    [device invokeCommandWithEndpointId:1
-                              clusterId:6
-                              commandId:1
-                          commandFields:fields
-                            clientQueue:queue
-                             completion:^(id _Nullable values, NSError * _Nullable error) {
-                                 NSLog(@"invoke command: On values: %@, error: %@", values, error);
-
-                                 XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
-
-                                 {
-                                     XCTAssertTrue([values isKindOfClass:[NSArray class]]);
-                                     NSArray * resultArray = values;
-                                     for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-                                         XCTAssertEqual([result[@"commandId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
-                                     }
-                                     XCTAssertEqual([resultArray count], 1);
-                                 }
-                                 [commandExpectation fulfill];
-                             }];
-    [self waitForExpectations:[NSArray arrayWithObject:commandExpectation] timeout:kTimeoutInSeconds];
-
-    // Wait for report
-    [self waitForExpectations:[NSArray arrayWithObject:reportExpectation] timeout:kTimeoutInSeconds];
-
-    // Set up expectation for 2nd report
-    reportExpectation = [self expectationWithDescription:@"receive OnOff attribute report"];
-    reportHandler = ^(id _Nullable value, NSError * _Nullable error) {
-        XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
-        XCTAssertTrue([value isKindOfClass:[NSDictionary class]]);
-        NSDictionary * result = value;
-        XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-        XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-        XCTAssertTrue([result[@"value"] isKindOfClass:[NSDictionary class]]);
-        if ([result[@"attributeId"] unsignedIntegerValue] == 0 && [result[@"value"][@"value"] boolValue] == NO) {
-            [reportExpectation fulfill];
-            reportHandler = nil;
-        }
-    };
-
-    // Send command to trigger attribute change
-    commandExpectation = [self expectationWithDescription:@"command responded"];
-    fields = [NSDictionary dictionaryWithObjectsAndKeys:@"Structure", @"type", [NSArray array], @"value", nil];
+    NSDictionary * fields = @{ @"type" : @"Structure", @"value" : @[] };
     [device invokeCommandWithEndpointId:1
                               clusterId:6
                               commandId:0
@@ -1012,10 +1099,88 @@
                                      XCTAssertTrue([values isKindOfClass:[NSArray class]]);
                                      NSArray * resultArray = values;
                                      for (NSDictionary * result in resultArray) {
-                                         XCTAssertEqual([result[@"endpointId"] unsignedIntegerValue], 1);
-                                         XCTAssertEqual([result[@"clusterId"] unsignedIntegerValue], 6);
-                                         XCTAssertEqual([result[@"commandId"] unsignedIntegerValue], 0);
-                                         XCTAssertEqual([result[@"status"] unsignedIntegerValue], 0);
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 0);
+                                         XCTAssertNil(result[@"error"]);
+                                     }
+                                     XCTAssertEqual([resultArray count], 1);
+                                 }
+                                 [commandExpectation fulfill];
+                             }];
+    [self waitForExpectations:[NSArray arrayWithObject:commandExpectation] timeout:kTimeoutInSeconds];
+
+    // Send commands to trigger attribute change
+    commandExpectation = [self expectationWithDescription:@"command responded"];
+    fields = @{ @"type" : @"Structure", @"value" : @[] };
+    [device invokeCommandWithEndpointId:1
+                              clusterId:6
+                              commandId:1
+                          commandFields:fields
+                            clientQueue:queue
+                             completion:^(id _Nullable values, NSError * _Nullable error) {
+                                 NSLog(@"invoke command: On values: %@, error: %@", values, error);
+
+                                 XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
+
+                                 {
+                                     XCTAssertTrue([values isKindOfClass:[NSArray class]]);
+                                     NSArray * resultArray = values;
+                                     for (NSDictionary * result in resultArray) {
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 1);
+                                         XCTAssertNil(result[@"error"]);
+                                     }
+                                     XCTAssertEqual([resultArray count], 1);
+                                 }
+                                 [commandExpectation fulfill];
+                             }];
+    [self waitForExpectations:[NSArray arrayWithObject:commandExpectation] timeout:kTimeoutInSeconds];
+
+    // Wait for report
+    [self waitForExpectations:[NSArray arrayWithObject:reportExpectation] timeout:kTimeoutInSeconds];
+
+    // Set up expectation for 2nd report
+    reportExpectation = [self expectationWithDescription:@"receive OnOff attribute report"];
+    reportHandler = ^(id _Nullable values, NSError * _Nullable error) {
+        XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
+        XCTAssertTrue([values isKindOfClass:[NSArray class]]);
+        NSDictionary * result = values[0];
+        CHIPAttributePath * path = result[@"attributePath"];
+        XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+        XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+        XCTAssertTrue([result[@"data"] isKindOfClass:[NSDictionary class]]);
+        if ([path.attribute unsignedIntegerValue] == 0 && [result[@"data"][@"value"] boolValue] == NO) {
+            [reportExpectation fulfill];
+            reportHandler = nil;
+        }
+    };
+
+    // Send command to trigger attribute change
+    commandExpectation = [self expectationWithDescription:@"command responded"];
+    fields = @{ @"type" : @"Structure", @"value" : @[] };
+    [device invokeCommandWithEndpointId:1
+                              clusterId:6
+                              commandId:0
+                          commandFields:fields
+                            clientQueue:queue
+                             completion:^(id _Nullable values, NSError * _Nullable error) {
+                                 NSLog(@"invoke command: On values: %@, error: %@", values, error);
+
+                                 XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:error], 0);
+
+                                 {
+                                     XCTAssertTrue([values isKindOfClass:[NSArray class]]);
+                                     NSArray * resultArray = values;
+                                     for (NSDictionary * result in resultArray) {
+                                         CHIPCommandPath * path = result[@"commandPath"];
+                                         XCTAssertEqual([path.endpoint unsignedIntegerValue], 1);
+                                         XCTAssertEqual([path.cluster unsignedIntegerValue], 6);
+                                         XCTAssertEqual([path.command unsignedIntegerValue], 0);
+                                         XCTAssertNil(result[@"error"]);
                                      }
                                      XCTAssertEqual([resultArray count], 1);
                                  }
@@ -1026,7 +1191,6 @@
     // Wait for report
     [self waitForExpectations:[NSArray arrayWithObject:reportExpectation] timeout:kTimeoutInSeconds];
 }
-#endif
 
 #if !MANUAL_INDIVIDUAL_TEST
 - (void)test999_TearDown
@@ -1058,6 +1222,17 @@
     XCTAssertTrue([output isEqualTo:input]);
 }
 
+- (void)testSignedInteger64Bits
+{
+    NSDictionary * input = [NSDictionary
+        dictionaryWithObjectsAndKeys:@"SignedInteger", @"type", [NSNumber numberWithInteger:-0x7000111122223333ll], @"value", nil];
+    id output = [CHIPDevice CHIPEncodeAndDecodeNSObject:input];
+    NSLog(@"Conversion input: %@\nOutput: %@", input, output);
+    XCTAssertNotNil(output);
+    XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
+    XCTAssertTrue([output isEqualTo:input]);
+}
+
 - (void)testUnsignedInteger
 {
     NSDictionary * input =
@@ -1069,6 +1244,17 @@
     XCTAssertTrue([output isEqualTo:input]);
 }
 
+- (void)testUnsignedInteger64Bits
+{
+    NSDictionary * input = [NSDictionary dictionaryWithObjectsAndKeys:@"UnsignedInteger", @"type",
+                                         [NSNumber numberWithUnsignedLongLong:0xCCCCDDDDEEEEFFFFull], @"value", nil];
+    id output = [CHIPDevice CHIPEncodeAndDecodeNSObject:input];
+    NSLog(@"Conversion input: %@\nOutput: %@", input, output);
+    XCTAssertNotNil(output);
+    XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
+    XCTAssertTrue([output isEqualTo:input]);
+}
+
 - (void)testBoolean
 {
     NSDictionary * input =
@@ -1110,9 +1296,8 @@
     NSLog(@"Conversion input: %@\nOutput: %@", input, output);
     XCTAssertNotNil(output);
     XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
-    // Note that conversion doesn't guarantee back to Float.
-    XCTAssertTrue([output[@"type"] isEqualToString:@"Float"] || [output[@"type"] isEqualToString:@"Double"]);
-    XCTAssertTrue(([output[@"value"] doubleValue] - [input[@"value"] doubleValue]) < 0.0001);
+    XCTAssertTrue([output[@"type"] isEqualToString:@"Float"]);
+    XCTAssertTrue(([output[@"value"] floatValue] - [input[@"value"] floatValue]) < 0.0001);
 }
 
 - (void)testDouble
@@ -1123,8 +1308,7 @@
     NSLog(@"Conversion input: %@\nOutput: %@", input, output);
     XCTAssertNotNil(output);
     XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
-    // Note that conversion doesn't guarantee back to Double.
-    XCTAssertTrue([output[@"type"] isEqualToString:@"Float"] || [output[@"type"] isEqualToString:@"Double"]);
+    XCTAssertTrue([output[@"type"] isEqualToString:@"Double"]);
     XCTAssertTrue(([output[@"value"] doubleValue] - [input[@"value"] doubleValue]) < 0.0001);
 }
 
@@ -1140,98 +1324,38 @@
 
 - (void)testStructure
 {
-    NSArray * inputFields = [NSArray
-        arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:1], @"tag",
-                                       [NSDictionary dictionaryWithObjectsAndKeys:@"Boolean", @"type", [NSNumber numberWithBool:NO],
-                                                     @"value", nil],
-                                       @"value", nil],
-        [NSDictionary
-            dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:2], @"tag",
-            [NSDictionary dictionaryWithObjectsAndKeys:@"SignedInteger", @"type", [NSNumber numberWithInteger:5], @"value", nil],
-            @"value", nil],
-        nil];
-    NSDictionary * inputValue = [NSDictionary dictionaryWithObjectsAndKeys:@"Structure", @"type", inputFields, @"value", nil];
-
-    // Output will have context tags and hence build object with context tags for comparison
-    NSMutableArray * contextTaggedInputFields = [NSMutableArray arrayWithCapacity:[inputFields count]];
-    for (NSDictionary * field in inputFields) {
-        [contextTaggedInputFields
-            addObject:[NSDictionary
-                          dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:([field[@"tag"] unsignedIntegerValue]
-                                                                                               | 0xffffffff00000000ull)],
-                          @"tag", field[@"value"], @"value", nil]];
-    }
+    NSArray * inputFields = @[
+        @{
+            @"contextTag" : @1,
+            @"data" : @ { @"type" : @"Boolean", @"value" : @NO },
+        },
+        @{
+            @"contextTag" : @2,
+            @"data" : @ { @"type" : @"SignedInteger", @"value" : @5 },
+        }
+    ];
+    NSDictionary * inputValue = @{ @"type" : @"Structure", @"value" : inputFields };
 
     id output = [CHIPDevice CHIPEncodeAndDecodeNSObject:inputValue];
     NSLog(@"Conversion input: %@\nOutput: %@", inputValue, output);
     XCTAssertNotNil(output);
     XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
 
-    NSDictionary * compare =
-        [NSDictionary dictionaryWithObjectsAndKeys:@"Structure", @"type", contextTaggedInputFields, @"value", nil];
-    XCTAssertTrue([output isEqualTo:compare]);
+    XCTAssertTrue([output isEqualTo:inputValue]);
 }
 
 - (void)testArray
 {
-    NSArray * inputFields = [NSArray
-        arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:[NSDictionary dictionaryWithObjectsAndKeys:@"Boolean", @"type",
-                                                                                  [NSNumber numberWithBool:NO], @"value", nil],
-                                       @"value", nil],
-        [NSDictionary dictionaryWithObjectsAndKeys:[NSDictionary dictionaryWithObjectsAndKeys:@"SignedInteger", @"type",
-                                                                 [NSNumber numberWithInteger:5], @"value", nil],
-                      @"value", nil],
-        nil];
-    NSDictionary * inputValue = [NSDictionary dictionaryWithObjectsAndKeys:@"Array", @"type", inputFields, @"value", nil];
-
-    // Output will have anonymous tags and hence build object with context tags for comparison
-    NSMutableArray * contextTaggedInputFields = [NSMutableArray arrayWithCapacity:[inputFields count]];
-    for (NSDictionary * field in inputFields) {
-        [contextTaggedInputFields
-            addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:0xffffffffffffffffull], @"tag",
-                                    field[@"value"], @"value", nil]];
-    }
+    NSArray * inputFields = @[
+        @{ @"data" : @ { @"type" : @"Boolean", @"value" : @NO } }, @{ @"data" : @ { @"type" : @"SignedInteger", @"value" : @5 } }
+    ];
+    NSDictionary * inputValue = @{ @"type" : @"Array", @"value" : inputFields };
 
     id output = [CHIPDevice CHIPEncodeAndDecodeNSObject:inputValue];
     NSLog(@"Conversion input: %@\nOutput: %@", inputValue, output);
     XCTAssertNotNil(output);
     XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
-
-    NSDictionary * compare = [NSDictionary dictionaryWithObjectsAndKeys:@"Array", @"type", contextTaggedInputFields, @"value", nil];
-    XCTAssertTrue([output isEqualTo:compare]);
-}
-
-- (void)testList
-{
-    NSArray * inputFields = [NSArray
-        arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:1], @"tag",
-                                       [NSDictionary dictionaryWithObjectsAndKeys:@"Boolean", @"type", [NSNumber numberWithBool:NO],
-                                                     @"value", nil],
-                                       @"value", nil],
-        [NSDictionary
-            dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:2], @"tag",
-            [NSDictionary dictionaryWithObjectsAndKeys:@"SignedInteger", @"type", [NSNumber numberWithInteger:5], @"value", nil],
-            @"value", nil],
-        nil];
-    NSDictionary * inputValue = [NSDictionary dictionaryWithObjectsAndKeys:@"List", @"type", inputFields, @"value", nil];
-
-    // Output will have context tags and hence build object with context tags for comparison
-    NSMutableArray * contextTaggedInputFields = [NSMutableArray arrayWithCapacity:[inputFields count]];
-    for (NSDictionary * field in inputFields) {
-        [contextTaggedInputFields
-            addObject:[NSDictionary
-                          dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInteger:([field[@"tag"] unsignedIntegerValue]
-                                                                                               | 0xffffffff00000000ull)],
-                          @"tag", field[@"value"], @"value", nil]];
-    }
-
-    id output = [CHIPDevice CHIPEncodeAndDecodeNSObject:inputValue];
-    NSLog(@"Conversion input: %@\nOutput: %@", inputValue, output);
-    XCTAssertNotNil(output);
-    XCTAssertTrue([output isKindOfClass:[NSDictionary class]]);
-
-    NSDictionary * compare = [NSDictionary dictionaryWithObjectsAndKeys:@"List", @"type", contextTaggedInputFields, @"value", nil];
-    XCTAssertTrue([output isEqualTo:compare]);
+    XCTAssertTrue([output isEqualTo:inputValue]);
 }
 
 @end