Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into Modified_yamls_matt…
Browse files Browse the repository at this point in the history
…er_1_3
  • Loading branch information
raul-marquez-csa committed Feb 15, 2024
2 parents cd44f3e + a71f814 commit 7b0d396
Show file tree
Hide file tree
Showing 27 changed files with 1,154 additions and 260 deletions.
1 change: 1 addition & 0 deletions scripts/build/build/targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def BuildHostTarget():
target.AppendModifier('nodeps', enable_ble=False, enable_wifi=False, enable_thread=False,
crypto_library=HostCryptoLibrary.MBEDTLS, use_clang=True).ExceptIfRe('-(clang|noble|boringssl|mbedtls)')

target.AppendModifier('nlfaultinject', use_nl_fault_injection=True)
target.AppendModifier('platform-mdns', use_platform_mdns=True)
target.AppendModifier('minmdns-verbose', minmdns_high_verbosity=True)
target.AppendModifier('libnl', minmdns_address_policy="libnl")
Expand Down
5 changes: 4 additions & 1 deletion scripts/build/builders/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE,
enable_ipv4=True, enable_ble=True, enable_wifi=True,
enable_thread=True, use_tsan=False, use_asan=False, use_ubsan=False,
separate_event_loop=True, fuzzing_type: HostFuzzingType = HostFuzzingType.NONE, use_clang=False,
interactive_mode=True, extra_tests=False, use_platform_mdns=False, enable_rpcs=False,
interactive_mode=True, extra_tests=False, use_nl_fault_injection=False, use_platform_mdns=False, enable_rpcs=False,
use_coverage=False, use_dmalloc=False, minmdns_address_policy=None,
minmdns_high_verbosity=False, imgui_ui=False, crypto_library: HostCryptoLibrary = None,
enable_test_event_triggers=None):
Expand Down Expand Up @@ -368,6 +368,9 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE,
# so setting clang is not correct
raise Exception('Fake host board is always gcc (not clang)')

if use_nl_fault_injection:
self.extra_gn_options.append('chip_with_nlfaultinjection=true')

if minmdns_address_policy:
if use_platform_mdns:
raise Exception('Address policy applies to minmdns only')
Expand Down
2 changes: 1 addition & 1 deletion scripts/build/testdata/all_targets_linux_x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,b
esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,energy-management,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only][-tracing]
genio-lighting-app
linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang]
linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event]
linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event]
linux-x64-efr32-test-runner[-clang]
imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release]
infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage]
Expand Down
4 changes: 2 additions & 2 deletions scripts/helpers/iwyu-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ def main(compile_commands_glob, scanning_destination, mapping_file_dir,
logging.info("============== IWYU output start ================")

logger = logging.info
while status.poll() is None:
line = status.stdout.readline().rstrip()
for line in status.stdout:
line = line.rstrip()

if re.match(r"^warning:.*$", line):
logger = logging.warning
Expand Down
5 changes: 5 additions & 0 deletions scripts/helpers/platforms/iwyu.imp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
## lib/*
{ include: [ '"lib/core/CHIPError.h"', private, '<lib/core/CHIPError.h>', public ] },
{ include: [ '"lib/dnssd/ServiceNaming.h"', private, '<lib/dnssd/platform/Dnssd.h>', public ] },

## lib/support/logging/*
{ include: [ '"lib/support/logging/BinaryLogging.h"', private, '<lib/support/logging/CHIPLogging.h>', public ] },
{ include: [ '"lib/support/logging/CHIPLogging.h"', private, '<lib/support/logging/CHIPLogging.h>', public ] },
{ include: [ '"lib/support/logging/Constants.h"', private, '<lib/support/logging/CHIPLogging.h>', public ] },
{ include: [ '"lib/support/logging/TextOnlyLogging.h"', private, '<lib/support/logging/CHIPLogging.h>', public ] },

## platform/*
{ include: [ '"platform/NetworkCommissioning.h"', private, '<platform/NetworkCommissioning.h>', public ] },
Expand Down
11 changes: 11 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ declare_args() {
chip_im_force_fabric_quota_check = false

enable_eventlist_attribute = false

# Systems that can spare a bit of RAM for InteractionModelEngine/delegate
# pointers should do so (allows InteractionModelEngine decoupling and less usage
# of global pointers)
chip_im_static_global_interaction_model_engine =
current_os != "linux" && current_os != "mac" && current_os != "ios" &&
current_os != "android"
}

buildconfig_header("app_buildconfig") {
Expand All @@ -57,6 +64,7 @@ buildconfig_header("app_buildconfig") {
"CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION=${chip_subscription_timeout_resumption}",
"CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE=${enable_eventlist_attribute}",
"CHIP_CONFIG_ENABLE_READ_CLIENT=${chip_enable_read_client}",
"CHIP_CONFIG_STATIC_GLOBAL_INTERACTION_MODEL_ENGINE=${chip_im_static_global_interaction_model_engine}",
]

visibility = [ ":app_config" ]
Expand Down Expand Up @@ -129,6 +137,8 @@ static_library("interaction-model") {
"CASESessionManager.h",
"DeviceProxy.cpp",
"DeviceProxy.h",
"InteractionModelDelegatePointers.cpp",
"InteractionModelDelegatePointers.h",
"InteractionModelEngine.cpp",
"InteractionModelEngine.h",
"InteractionModelTimeout.h",
Expand Down Expand Up @@ -161,6 +171,7 @@ static_library("interaction-model") {
"${chip_root}/src/app/icd/server:observer",
"${chip_root}/src/lib/address_resolve",
"${chip_root}/src/lib/support",
"${chip_root}/src/lib/support:static-support",
"${chip_root}/src/protocols/interaction_model",
"${chip_root}/src/protocols/secure_channel",
"${chip_root}/src/system",
Expand Down
130 changes: 130 additions & 0 deletions src/app/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ Status CommandHandler::ProcessInvokeRequest(System::PacketBufferHandle && payloa
SetGroupRequest(true);
}

// When updating this code, please remember to make corresponding changes to TestOnlyInvokeCommandRequestWithFaultsInjected.
VerifyOrReturnError(invokeRequestMessage.GetSuppressResponse(&mSuppressResponse) == CHIP_NO_ERROR, Status::InvalidAction);
VerifyOrReturnError(invokeRequestMessage.GetTimedRequest(&mTimedRequest) == CHIP_NO_ERROR, Status::InvalidAction);
VerifyOrReturnError(invokeRequestMessage.GetInvokeRequests(&invokeRequests) == CHIP_NO_ERROR, Status::InvalidAction);
Expand Down Expand Up @@ -911,6 +912,135 @@ void CommandHandler::MoveToState(const State aTargetState)
ChipLogDetail(DataManagement, "Command handler moving to [%10.10s]", GetStateStr());
}

#if CHIP_WITH_NLFAULTINJECTION

namespace {

CHIP_ERROR TestOnlyExtractCommandPathFromNextInvokeRequest(TLV::TLVReader & invokeRequestsReader,
ConcreteCommandPath & concretePath)
{
ReturnErrorOnFailure(invokeRequestsReader.Next(TLV::AnonymousTag()));
CommandDataIB::Parser commandData;
ReturnErrorOnFailure(commandData.Init(invokeRequestsReader));
CommandPathIB::Parser commandPath;
ReturnErrorOnFailure(commandData.GetPath(&commandPath));
return commandPath.GetConcreteCommandPath(concretePath);
}

[[maybe_unused]] const char * GetFaultInjectionTypeStr(CommandHandler::NlFaultInjectionType faultType)
{
switch (faultType)
{
case CommandHandler::NlFaultInjectionType::SeparateResponseMessages:
return "Each response will be sent in a separate InvokeResponseMessage. The order of responses will be the same as the "
"original request.";
case CommandHandler::NlFaultInjectionType::SeparateResponseMessagesAndInvertedResponseOrder:
return "Each response will be sent in a separate InvokeResponseMessage. The order of responses will be reversed from the "
"original request.";
case CommandHandler::NlFaultInjectionType::SkipSecondResponse:
return "Single InvokeResponseMessages. Dropping response to second request";
}
VerifyOrDieWithMsg(false, DataManagement, "TH Failure: Unexpected fault type");
}

} // anonymous namespace

// This method intentionally duplicates code from other sections. While code consolidation
// is generally preferred, here we prioritize generating a clear crash message to aid in
// troubleshooting test failures.
void CommandHandler::TestOnlyInvokeCommandRequestWithFaultsInjected(Messaging::ExchangeContext * ec,
System::PacketBufferHandle && payload, bool isTimedInvoke,
NlFaultInjectionType faultType)
{
VerifyOrDieWithMsg(ec != nullptr, DataManagement, "TH Failure: Incoming exchange context should not be null");
VerifyOrDieWithMsg(mState == State::Idle, DataManagement, "TH Failure: state should be Idle, issue with TH");

ChipLogProgress(DataManagement, "Response to InvokeRequestMessage overridden by fault injection");
ChipLogProgress(DataManagement, " Injecting the following response:%s", GetFaultInjectionTypeStr(faultType));

mResponseSender.SetExchangeContext(ec);
Handle workHandle(this);
mResponseSender.WillSendMessage();
VerifyOrDieWithMsg(!mResponseSender.IsForGroup(), DataManagement, "DUT Failure: Unexpected Group Command");

System::PacketBufferTLVReader reader;
InvokeRequestMessage::Parser invokeRequestMessage;
InvokeRequests::Parser invokeRequests;
reader.Init(std::move(payload));
VerifyOrDieWithMsg(invokeRequestMessage.Init(reader) == CHIP_NO_ERROR, DataManagement,
"TH Failure: Failed 'invokeRequestMessage.Init(reader)'");
#if CHIP_CONFIG_IM_PRETTY_PRINT
invokeRequestMessage.PrettyPrint();
#endif

VerifyOrDieWithMsg(invokeRequestMessage.GetSuppressResponse(&mSuppressResponse) == CHIP_NO_ERROR, DataManagement,
"DUT Failure: Mandatory SuppressResponse field missing");
VerifyOrDieWithMsg(invokeRequestMessage.GetTimedRequest(&mTimedRequest) == CHIP_NO_ERROR, DataManagement,
"DUT Failure: Mandatory TimedRequest field missing");
VerifyOrDieWithMsg(invokeRequestMessage.GetInvokeRequests(&invokeRequests) == CHIP_NO_ERROR, DataManagement,
"DUT Failure: Mandatory InvokeRequests field missing");
VerifyOrDieWithMsg(mTimedRequest == isTimedInvoke, DataManagement,
"DUT Failure: TimedRequest value in message mismatches action");

{
InvokeRequestMessage::Parser validationInvokeRequestMessage = invokeRequestMessage;
VerifyOrDieWithMsg(ValidateInvokeRequestMessageAndBuildRegistry(validationInvokeRequestMessage) == CHIP_NO_ERROR,
DataManagement, "DUT Failure: InvokeRequestMessage contents were invalid");
}

TLV::TLVReader invokeRequestsReader;
invokeRequests.GetReader(&invokeRequestsReader);

size_t commandCount = 0;
VerifyOrDieWithMsg(TLV::Utilities::Count(invokeRequestsReader, commandCount, false /* recurse */) == CHIP_NO_ERROR,
DataManagement,
"TH Failure: Failed to get the length of InvokeRequests after InvokeRequestMessage validation");

// The command count check (specifically for a count of 2) is tied to IDM_1_3. This may need adjustment for
// compatibility with future test plans.
VerifyOrDieWithMsg(commandCount == 2, DataManagement, "DUT failure: We were strictly expecting exactly 2 InvokeRequests");
mReserveSpaceForMoreChunkMessages = true;

{
// Response path is the same as request path since we are replying with a failure message.
ConcreteCommandPath concreteResponsePath1;
ConcreteCommandPath concreteResponsePath2;
VerifyOrDieWithMsg(
TestOnlyExtractCommandPathFromNextInvokeRequest(invokeRequestsReader, concreteResponsePath1) == CHIP_NO_ERROR,
DataManagement, "DUT Failure: Issues encountered while extracting the ConcreteCommandPath from the first request");
VerifyOrDieWithMsg(
TestOnlyExtractCommandPathFromNextInvokeRequest(invokeRequestsReader, concreteResponsePath2) == CHIP_NO_ERROR,
DataManagement, "DUT Failure: Issues encountered while extracting the ConcreteCommandPath from the second request");

if (faultType == NlFaultInjectionType::SeparateResponseMessagesAndInvertedResponseOrder)
{
ConcreteCommandPath temp(concreteResponsePath1);
concreteResponsePath1 = concreteResponsePath2;
concreteResponsePath2 = temp;
}

VerifyOrDieWithMsg(FallibleAddStatus(concreteResponsePath1, Status::Failure) == CHIP_NO_ERROR, DataManagement,
"TH Failure: Error adding the first InvokeResponse");
if (faultType == NlFaultInjectionType::SeparateResponseMessages ||
faultType == NlFaultInjectionType::SeparateResponseMessagesAndInvertedResponseOrder)
{
VerifyOrDieWithMsg(FinalizeInvokeResponseMessageAndPrepareNext() == CHIP_NO_ERROR, DataManagement,
"TH Failure: Failed to create second InvokeResponseMessage");
}
if (faultType != NlFaultInjectionType::SkipSecondResponse)
{
VerifyOrDieWithMsg(FallibleAddStatus(concreteResponsePath2, Status::Failure) == CHIP_NO_ERROR, DataManagement,
"TH Failure: Error adding the second InvokeResponse");
}
}

VerifyOrDieWithMsg(invokeRequestsReader.Next() == CHIP_END_OF_TLV, DataManagement,
"DUT Failure: Unexpected TLV ending of InvokeRequests");
VerifyOrDieWithMsg(invokeRequestMessage.ExitContainer() == CHIP_NO_ERROR, DataManagement,
"DUT Failure: InvokeRequestMessage TLV is not properly terminated");
}
#endif // CHIP_WITH_NLFAULTINJECTION

} // namespace app
} // namespace chip

Expand Down
29 changes: 29 additions & 0 deletions src/app/CommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,35 @@ class CommandHandler
return mResponseSender.GetSubjectDescriptor();
}

#if CHIP_WITH_NLFAULTINJECTION

enum class NlFaultInjectionType : uint8_t
{
SeparateResponseMessages,
SeparateResponseMessagesAndInvertedResponseOrder,
SkipSecondResponse
};

/**
* @brief Sends InvokeResponseMessages with injected faults for certification testing.
*
* The Test Harness (TH) uses this to simulate various server response behaviors,
* ensuring the Device Under Test (DUT) handles responses per specification.
*
* This function strictly validates the DUT's InvokeRequestMessage against the test plan.
* If deviations occur, the TH terminates with a detailed error message.
*
* @param ec Exchange context for sending InvokeResponseMessages to the client.
* @param payload Payload of the incoming InvokeRequestMessage from the client.
* @param isTimedInvoke Indicates whether the interaction is timed.
* @param faultType The specific type of fault to inject into the response.
*/
// TODO(#30453): After refactoring CommandHandler for better unit testability, create a
// unit test specifically for the fault injection behavior.
void TestOnlyInvokeCommandRequestWithFaultsInjected(Messaging::ExchangeContext * ec, System::PacketBufferHandle && payload,
bool isTimedInvoke, NlFaultInjectionType faultType);
#endif // CHIP_WITH_NLFAULTINJECTION

private:
friend class TestCommandInteraction;
friend class CommandHandler::Handle;
Expand Down
2 changes: 2 additions & 0 deletions src/app/ConcreteCommandPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ struct ConcreteCommandPath : public ConcreteClusterPath
ConcreteClusterPath(aEndpointId, aClusterId), mCommandId(aCommandId)
{}

ConcreteCommandPath() : ConcreteClusterPath(kInvalidEndpointId, kInvalidClusterId), mCommandId(kInvalidCommandId) {}

bool operator==(const ConcreteCommandPath & aOther) const
{
return ConcreteClusterPath::operator==(aOther) && (mCommandId == aOther.mCommandId);
Expand Down
36 changes: 36 additions & 0 deletions src/app/InteractionModelDelegatePointers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InteractionModelDelegatePointers.h"

#if CHIP_CONFIG_STATIC_GLOBAL_INTERACTION_MODEL_ENGINE

// TODO: It would be nice to not need to couple the pointers class
// to the global interaction model engine
#include "InteractionModelEngine.h"

namespace chip {

template <>
app::TimedHandlerDelegate * GlobalInstanceProvider<app::TimedHandlerDelegate>::InstancePointer()
{
return app::InteractionModelEngine::GetInstance();
}

} // namespace chip

#endif
37 changes: 37 additions & 0 deletions src/app/InteractionModelDelegatePointers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once

#include <app/AppConfig.h>
#include <lib/support/static_support_smart_ptr.h>

namespace chip {

#if CHIP_CONFIG_STATIC_GLOBAL_INTERACTION_MODEL_ENGINE

template <class T>
using InteractionModelDelegatePointer = chip::CheckedGlobalInstanceReference<T>;

#else

template <class T>
using InteractionModelDelegatePointer = chip::SimpleInstanceReference<T>;

#endif // CHIP_CONFIG_STATIC_GLOBAL_INTERATION_MODEL_ENGINE

} // namespace chip
Loading

0 comments on commit 7b0d396

Please sign in to comment.