How to use dumpRaw method in fMBT

Best Python code snippet using fMBT_python

mutiny.py

Source:mutiny.py Github

copy

Full Screen

1#!/usr/bin/env python2#------------------------------------------------------------------3# November 2014, created within ASIG4# Author James Spadaro (jaspadar)5# Co-Author Lilith Wyatt (liwyatt)6#------------------------------------------------------------------7# Copyright (c) 2014-2017 by Cisco Systems, Inc.8# All rights reserved.9#10# Redistribution and use in source and binary forms, with or without11# modification, are permitted provided that the following conditions are met:12# 1. Redistributions of source code must retain the above copyright13# notice, this list of conditions and the following disclaimer.14# 2. Redistributions in binary form must reproduce the above copyright15# notice, this list of conditions and the following disclaimer in the16# documentation and/or other materials provided with the distribution.17# 3. Neither the name of the Cisco Systems, Inc. nor the18# names of its contributors may be used to endorse or promote products19# derived from this software without specific prior written permission.20#21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY22# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED23# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY25# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES26# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;27# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND28# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS30# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31#------------------------------------------------------------------32#33# This is the main fuzzing script. It takes a .fuzzer file and performs the34# actual fuzzing35#36#------------------------------------------------------------------37import datetime38import errno39import importlib40import os.path41import os42import signal43import socket44import subprocess45import sys46import threading47import time48import argparse49import ssl50from copy import deepcopy51from backend.proc_director import ProcDirector52from backend.fuzzer_types import Message, MessageCollection, Logger53from backend.packets import PROTO,IP54from mutiny_classes.mutiny_exceptions import *55from mutiny_classes.message_processor import MessageProcessorExtraParams56from backend.fuzzerdata import FuzzerData57from backend.menu_functions import validateNumberRange58# Path to Radamsa binary59RADAMSA=os.path.abspath( os.path.join(__file__, "../radamsa-0.6/bin/radamsa") )60# Whether to print debug info61DEBUG_MODE=False62# Test number to start from, 0 default63MIN_RUN_NUMBER=064# Test number to go to, -1 is unlimited65MAX_RUN_NUMBER=-166# For seed loop, finite range to repeat 67SEED_LOOP = []68# For dumpraw option, dump into log directory by default, else 'dumpraw'69DUMPDIR = ""70# Takes a socket and outbound data packet (byteArray), sends it out.71# If debug mode is enabled, we print out the raw bytes72def sendPacket(connection, addr, outPacketData):73 connection.settimeout(fuzzerData.receiveTimeout)74 if connection.type == socket.SOCK_STREAM:75 connection.send(outPacketData)76 else:77 connection.sendto(outPacketData,addr)78 print("\tSent %d byte packet" % (len(outPacketData)))79 if DEBUG_MODE:80 print("\tSent: %s" % (outPacketData))81 print("\tRaw Bytes: %s" % (Message.serializeByteArray(outPacketData)))82def receivePacket(connection, addr, bytesToRead):83 readBufSize = 409684 connection.settimeout(fuzzerData.receiveTimeout)85 if connection.type == socket.SOCK_STREAM or connection.type == socket.SOCK_DGRAM:86 response = bytearray(connection.recv(readBufSize))87 else:88 response = bytearray(connection.recvfrom(readBufSize,addr))89 90 91 if len(response) == 0:92 # If 0 bytes are recv'd, the server has closed the connection93 # per python documentation94 raise ConnectionClosedException("Server has closed the connection")95 if bytesToRead > readBufSize:96 # If we're trying to read > 4096, don't actually bother trying to guarantee we'll read 409697 # Just keep reading in 4096 chunks until we should have read enough, and then return98 # whether or not it's as much data as expected99 i = readBufSize100 while i < bytesToRead:101 response += bytearray(connection.recv(readBufSize))102 i += readBufSize103 104 print("\tReceived %d bytes" % (len(response)))105 if DEBUG_MODE:106 print("\tReceived: %s" % (response))107 return response108# Perform a fuzz run. 109# If seed is -1, don't perform fuzzing (test run)110def performRun(fuzzerData, host, logger, messageProcessor, seed=-1):111 # Before doing anything, set up logger112 # Otherwise, if connection is refused, we'll log last, but it will be wrong113 if logger != None:114 logger.resetForNewRun()115 116 addrs = socket.getaddrinfo(host,fuzzerData.port)117 host = addrs[0][4][0]118 if host == "::1":119 host = "127.0.0.1"120 121 # cheap testing for ipv6/ipv4/unix122 # don't think it's worth using regex for this, since the user123 # will have to actively go out of their way to subvert this.124 if "." in host:125 socket_family = socket.AF_INET126 addr = (host,fuzzerData.port)127 elif ":" in host:128 socket_family = socket.AF_INET6 129 addr = (host,fuzzerData.port)130 else:131 socket_family = socket.AF_UNIX132 addr = (host)133 #just in case filename is like "./asdf" !=> AF_INET134 if "/" in host:135 socket_family = socket.AF_UNIX136 addr = (host)137 138 # Call messageprocessor preconnect callback if it exists139 try:140 messageProcessor.preConnect(seed, host, fuzzerData.port) 141 except AttributeError:142 pass143 144 # for TCP/UDP/RAW support145 if fuzzerData.proto == "tcp":146 connection = socket.socket(socket_family,socket.SOCK_STREAM)147 # Don't connect yet, until after we do any binding below148 elif fuzzerData.proto == "tls":149 try:150 _create_unverified_https_context = ssl._create_unverified_context151 except AttributeError:152 # Legacy Python that doesn't verify HTTPS certificates by default153 pass154 else:155 # Handle target environment that doesn't support HTTPS verification156 ssl._create_default_https_context = _create_unverified_https_context157 tcpConnection = socket.socket(socket_family,socket.SOCK_STREAM)158 connection = ssl.wrap_socket(tcpConnection)159 # Don't connect yet, until after we do any binding below160 elif fuzzerData.proto == "udp":161 connection = socket.socket(socket_family,socket.SOCK_DGRAM)162 # PROTO = dictionary of assorted L3 proto => proto number163 # e.g. "icmp" => 1164 elif fuzzerData.proto in PROTO:165 connection = socket.socket(socket_family,socket.SOCK_RAW,PROTO[fuzzerData.proto]) 166 if fuzzerData.proto != "raw":167 connection.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,0)168 addr = (host,0)169 try:170 connection = socket.socket(socket_family,socket.SOCK_RAW,PROTO[fuzzerData.proto]) 171 except Exception as e:172 print(e)173 print("Unable to create raw socket, please verify that you have sudo access")174 sys.exit(0)175 elif fuzzerData.proto == "L2raw":176 connection = socket.socket(socket.AF_PACKET,socket.SOCK_RAW,0x0300)177 else:178 addr = (host,0)179 try:180 #test if it's a valid number 181 connection = socket.socket(socket_family,socket.SOCK_RAW,int(fuzzerData.proto)) 182 connection.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,0)183 except Exception as e:184 print(e)185 print("Unable to create raw socket, please verify that you have sudo access")186 sys.exit(0)187 188 if fuzzerData.proto == "tcp" or fuzzerData.proto == "udp" or fuzzerData.proto == "tls":189 # Specifying source port or address is only supported for tcp and udp currently190 if fuzzerData.sourcePort != -1:191 # Only support right now for tcp or udp, but bind source port address to something192 # specific if requested193 if fuzzerData.sourceIP != "" or fuzzerData.sourceIP != "0.0.0.0":194 connection.bind((fuzzerData.sourceIP, fuzzerData.sourcePort))195 else:196 # User only specified a port, not an IP197 connection.bind(('0.0.0.0', fuzzerData.sourcePort))198 elif fuzzerData.sourceIP != "" and fuzzerData.sourceIP != "0.0.0.0":199 # No port was specified, so 0 should auto-select200 connection.bind((fuzzerData.sourceIP, 0))201 if fuzzerData.proto == "tcp" or fuzzerData.proto == "tls":202 # Now that we've had a chance to bind as necessary, connect203 connection.connect(addr)204 i = 0 205 for i in range(0, len(fuzzerData.messageCollection.messages)):206 message = fuzzerData.messageCollection.messages[i]207 208 # Go ahead and revert any fuzzing or messageprocessor changes before proceeding209 message.resetAlteredMessage()210 if message.isOutbound():211 # Primarily used for deciding how to handle preFuzz/preSend callbacks212 doesMessageHaveSubcomponents = len(message.subcomponents) > 1213 # Get original subcomponents for outbound callback only once214 originalSubcomponents = [subcomponent.getOriginalByteArray() for subcomponent in message.subcomponents]215 216 if doesMessageHaveSubcomponents:217 # For message with subcomponents, call prefuzz on fuzzed subcomponents218 for j in range(0, len(message.subcomponents)):219 subcomponent = message.subcomponents[j] 220 # Note: we WANT to fetch subcomponents every time on purpose221 # This way, if user alters subcomponent[0], it's reflected when222 # we call the function for subcomponent[1], etc223 actualSubcomponents = [subcomponent.getAlteredByteArray() for subcomponent in message.subcomponents]224 prefuzz = messageProcessor.preFuzzSubcomponentProcess(subcomponent.getAlteredByteArray(), MessageProcessorExtraParams(i, j, subcomponent.isFuzzed, originalSubcomponents, actualSubcomponents))225 subcomponent.setAlteredByteArray(prefuzz)226 else:227 # If no subcomponents, call prefuzz on ENTIRE message228 actualSubcomponents = [subcomponent.getAlteredByteArray() for subcomponent in message.subcomponents]229 prefuzz = messageProcessor.preFuzzProcess(actualSubcomponents[0], MessageProcessorExtraParams(i, -1, message.isFuzzed, originalSubcomponents, actualSubcomponents))230 message.subcomponents[0].setAlteredByteArray(prefuzz)231 # Skip fuzzing for seed == -1232 if seed > -1:233 # Now run the fuzzer for each fuzzed subcomponent234 for subcomponent in message.subcomponents:235 if subcomponent.isFuzzed:236 radamsa = subprocess.Popen([RADAMSA, "--seed", str(seed)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)237 byteArray = subcomponent.getAlteredByteArray()238 (fuzzedByteArray, error_output) = radamsa.communicate(input=byteArray)239 fuzzedByteArray = bytearray(fuzzedByteArray)240 subcomponent.setAlteredByteArray(fuzzedByteArray)241 242 # Fuzzing has now been done if this message is fuzzed243 # Always call preSend() regardless for subcomponents if there are any244 if doesMessageHaveSubcomponents:245 for j in range(0, len(message.subcomponents)):246 subcomponent = message.subcomponents[j] 247 # See preFuzz above - we ALWAYS regather this to catch any updates between248 # callbacks from the user249 actualSubcomponents = [subcomponent.getAlteredByteArray() for subcomponent in message.subcomponents]250 presend = messageProcessor.preSendSubcomponentProcess(subcomponent.getAlteredByteArray(), MessageProcessorExtraParams(i, j, subcomponent.isFuzzed, originalSubcomponents, actualSubcomponents))251 subcomponent.setAlteredByteArray(presend)252 253 # Always let the user make any final modifications pre-send, fuzzed or not254 actualSubcomponents = [subcomponent.getAlteredByteArray() for subcomponent in message.subcomponents]255 byteArrayToSend = messageProcessor.preSendProcess(message.getAlteredMessage(), MessageProcessorExtraParams(i, -1, message.isFuzzed, originalSubcomponents, actualSubcomponents))256 if args.dumpraw:257 loc = os.path.join(DUMPDIR,"%d-outbound-seed-%d"%(i,args.dumpraw))258 if message.isFuzzed:259 loc+="-fuzzed"260 with open(loc,"wb") as f:261 f.write(repr(str(byteArrayToSend))[1:-1])262 sendPacket(connection, addr, byteArrayToSend)263 else: 264 # Receiving packet from server265 messageByteArray = message.getAlteredMessage()266 data = receivePacket(connection,addr,len(messageByteArray))267 if data == messageByteArray:268 print("\tReceived expected response")269 if logger != None:270 logger.setReceivedMessageData(i, data)271 272 messageProcessor.postReceiveProcess(data, MessageProcessorExtraParams(i, -1, False, [messageByteArray], [data]))273 if args.dumpraw:274 loc = os.path.join(DUMPDIR,"%d-inbound-seed-%d"%(i,args.dumpraw))275 with open(loc,"wb") as f:276 f.write(repr(str(data))[1:-1])277 if logger != None: 278 logger.setHighestMessageNumber(i)279 280 i += 1281 282 connection.close()283# Usage case284if len(sys.argv) < 3:285 sys.argv.append('-h')286#TODO: add description/license/ascii art print out??287desc = "======== The Mutiny Fuzzing Framework ==========" 288epi = "==" * 24 + '\n'289parser = argparse.ArgumentParser(description=desc,epilog=epi)290parser.add_argument("prepped_fuzz", help="Path to file.fuzzer")291parser.add_argument("target_host", help="Target to fuzz")292parser.add_argument("-s","--sleeptime",help="Time to sleep between fuzz cases (float)",type=float,default=0)293seed_constraint = parser.add_mutually_exclusive_group()294seed_constraint.add_argument("-r", "--range", help="Run only the specified cases. Acceptable arg formats: [ X | X- | X-Y ], for integers X,Y") 295seed_constraint.add_argument("-l", "--loop", help="Loop/repeat the given finite number range. Acceptible arg format: [ X | X-Y | X,Y,Z-Q,R | ...]")296seed_constraint.add_argument("-d", "--dumpraw", help="Test single seed, dump to 'dumpraw' folder",type=int)297verbosity = parser.add_mutually_exclusive_group()298verbosity.add_argument("-q", "--quiet", help="Don't log the outputs",action="store_true")299verbosity.add_argument("--logAll", help="Log all the outputs",action="store_true")300args = parser.parse_args()301#----------------------------------------------------302# Set MIN_RUN_NUMBER and MAX_RUN_NUMBER when provided303# by the user below304def getRunNumbersFromArgs(strArgs):305 if "-" in strArgs:306 testNumbers = strArgs.split("-")307 if len(testNumbers) == 2:308 if len(testNumbers[1]): #e.g. strArgs="1-50"309 return (int(testNumbers[0]), int(testNumbers[1]))310 else: #e.g. strArgs="3-" (equiv. of --skip-to)311 return (int(testNumbers[0]),-1)312 else: #e.g. strArgs="1-2-3-5.." 313 sys.exit("Invalid test range given: %s" % args)314 else:315 # If they pass a non-int, allow this to bomb out316 return (int(strArgs),int(strArgs)) 317#----------------------------------------------------318#Populate global arguments from parseargs319fuzzerFilePath = args.prepped_fuzz320host = args.target_host321#Assign Lower/Upper bounds on test cases as needed322if args.range:323 (MIN_RUN_NUMBER, MAX_RUN_NUMBER) = getRunNumbersFromArgs(args.range)324elif args.loop:325 SEED_LOOP = validateNumberRange(args.loop,True) 326#Check for dependency binaries327if not os.path.exists(RADAMSA):328 sys.exit("Could not find radamsa in %s... did you build it?" % RADAMSA)329#Logging options330isReproduce = False331logAll = False332if args.quiet:333 isReproduce = True334elif args.logAll:335 logAll = True336outputDataFolderPath = os.path.join("%s_%s" % (os.path.splitext(fuzzerFilePath)[0], "logs"), datetime.datetime.now().strftime("%Y-%m-%d,%H%M%S"))337fuzzerFolder = os.path.abspath(os.path.dirname(fuzzerFilePath))338########## Declare variables for scoping, "None"s will be assigned below339messageProcessor = None340monitor = None341###Here we read in the fuzzer file into a dictionary for easier variable propagation342optionDict = {"unfuzzedBytes":{}, "message":[]}343fuzzerData = FuzzerData()344print("Reading in fuzzer data from %s..." % (fuzzerFilePath))345fuzzerData.readFromFile(fuzzerFilePath)346######## Processor Setup ################347# The processor just acts as a container #348# class that will import custom versions #349# messageProcessor/exceptionProessor/ #350# monitor, if they are found in the #351# process_dir specified in the .fuzzer #352# file generated by fuzz_prep.py #353##########################################354# Assign options to variables, error on anything that's missing/invalid355processorDirectory = fuzzerData.processorDirectory356if processorDirectory == "default":357 # Default to fuzzer file folder358 processorDirectory = fuzzerFolder359else:360 # Make sure fuzzer file path is prepended361 processorDirectory = os.path.join(fuzzerFolder, processorDirectory)362#Create class director, which import/overrides processors as appropriate363procDirector = ProcDirector(processorDirectory)364########## Launch child monitor thread365 ### monitor.task = spawned thread366 ### monitor.crashEvent = threading.Event()367monitor = procDirector.startMonitor(host,fuzzerData.port)368#! make it so logging message does not appear if reproducing (i.e. -r x-y cmdline arg is set)369logger = None 370if not isReproduce:371 print("Logging to %s" % (outputDataFolderPath))372 logger = Logger(outputDataFolderPath)373if args.dumpraw:374 if not isReproduce:375 DUMPDIR = outputDataFolderPath376 else:377 DUMPDIR = "dumpraw"378 try:379 os.mkdir("dumpraw")380 except:381 print("Unable to create dumpraw dir")382 pass383 384exceptionProcessor = procDirector.exceptionProcessor()385messageProcessor = procDirector.messageProcessor()386# Set up signal handler for CTRL+C and signals from child monitor thread387# since this is the same signal, we use the monitor.crashEvent flag()388# to differentiate between a CTRL+C and a interrupt_main() call from child 389def sigint_handler(signal, frame):390 if not monitor.crashEvent.isSet():391 # No event = quit392 # Quit on ctrl-c393 print("\nSIGINT received, stopping\n")394 sys.exit(0)395signal.signal(signal.SIGINT, sigint_handler)396########## Begin fuzzing397i = MIN_RUN_NUMBER-1 if fuzzerData.shouldPerformTestRun else MIN_RUN_NUMBER398failureCount = 0399loop_len = len(SEED_LOOP) # if --loop400while True:401 lastMessageCollection = deepcopy(fuzzerData.messageCollection)402 wasCrashDetected = False403 print("\n** Sleeping for %.3f seconds **" % args.sleeptime)404 time.sleep(args.sleeptime)405 406 try:407 try:408 if args.dumpraw:409 print("\n\nPerforming single raw dump case: %d" % args.dumpraw)410 performRun(fuzzerData, host, logger, messageProcessor, seed=args.dumpraw) 411 elif i == MIN_RUN_NUMBER-1:412 print("\n\nPerforming test run without fuzzing...")413 performRun(fuzzerData, host, logger, messageProcessor, seed=-1) 414 elif loop_len: 415 print("\n\nFuzzing with seed %d" % (SEED_LOOP[i%loop_len]))416 performRun(fuzzerData, host, logger, messageProcessor, seed=SEED_LOOP[i%loop_len]) 417 else:418 print("\n\nFuzzing with seed %d" % (i))419 performRun(fuzzerData, host, logger, messageProcessor, seed=i) 420 #if --quiet, (logger==None) => AttributeError421 if logAll:422 try:423 logger.outputLog(i, fuzzerData.messageCollection, "LogAll ")424 except AttributeError:425 pass426 427 except Exception as e:428 if monitor.crashEvent.isSet():429 print("Crash event detected")430 try:431 logger.outputLog(i, fuzzerData.messageCollection, "Crash event detected")432 #exit()433 except AttributeError: 434 pass435 monitor.crashEvent.clear()436 elif logAll:437 try:438 logger.outputLog(i, fuzzerData.messageCollection, "LogAll ")439 except AttributeError:440 pass441 442 if e.__class__ in MessageProcessorExceptions.all:443 # If it's a MessageProcessorException, assume the MP raised it during the run444 # Otherwise, let the MP know about the exception445 raise e446 else:447 exceptionProcessor.processException(e)448 # Will not get here if processException raises another exception449 print("Exception ignored: %s" % (str(e)))450 451 except LogCrashException as e:452 if failureCount == 0:453 try:454 print("MessageProcessor detected a crash")455 logger.outputLog(i, fuzzerData.messageCollection, str(e))456 except AttributeError: 457 pass 458 if logAll:459 try:460 logger.outputLog(i, fuzzerData.messageCollection, "LogAll ")461 except AttributeError:462 pass463 failureCount = failureCount + 1464 wasCrashDetected = True465 except AbortCurrentRunException as e:466 # Give up on the run early, but continue to the next test467 # This means the run didn't produce anything meaningful according to the processor468 print("Run aborted: %s" % (str(e)))469 470 except RetryCurrentRunException as e:471 # Same as AbortCurrentRun but retry the current test rather than skipping to next472 print("Retrying current run: %s" % (str(e)))473 # Slightly sketchy - a continue *should* just go to the top of the while without changing i474 continue475 476 except LogAndHaltException as e:477 if logger:478 logger.outputLog(i, fuzzerData.messageCollection, str(e))479 print("Received LogAndHaltException, logging and halting")480 else:481 print("Received LogAndHaltException, halting but not logging (quiet mode)")482 exit()483 484 except LogLastAndHaltException as e:485 if logger:486 if i > MIN_RUN_NUMBER:487 print("Received LogLastAndHaltException, logging last run and halting")488 if MIN_RUN_NUMBER == MAX_RUN_NUMBER:489 #in case only 1 case is run490 logger.outputLastLog(i, lastMessageCollection, str(e))491 print("Logged case %d" % i)492 else:493 logger.outputLastLog(i-1, lastMessageCollection, str(e))494 else:495 print("Received LogLastAndHaltException, skipping logging (due to last run being a test run) and halting")496 else:497 print("Received LogLastAndHaltException, halting but not logging (quiet mode)")498 exit()499 except HaltException as e:500 print("Received HaltException halting")501 exit()502 if wasCrashDetected:503 if failureCount < fuzzerData.failureThreshold:504 print("Failure %d of %d allowed for seed %d" % (failureCount, fuzzerData.failureThreshold, i))505 print("The test run didn't complete, continuing after %d seconds..." % (fuzzerData.failureTimeout))506 time.sleep(fuzzerData.failureTimeout)507 else:508 print("Failed %d times, moving to next test." % (failureCount))509 failureCount = 0510 i += 1511 else:512 i += 1513 514 # Stop if we have a maximum and have hit it515 if MAX_RUN_NUMBER >= 0 and i > MAX_RUN_NUMBER:516 exit()517 if args.dumpraw:518 exit()...

Full Screen

Full Screen

LmfSource.py

Source:LmfSource.py Github

copy

Full Screen

1import FWCore.ParameterSet.Config as cms2process = cms.Process("LmfTest")3process.maxEvents = cms.untracked.PSet(4 input = cms.untracked.int32(1000)5)6# MessageLogger:7process.load("FWCore.MessageLogger.MessageLogger_cfi")8process.MessageLogger.cerr.FwkReport.limit = 09#LMF source (lmfSource)10process.load("CalibCalorimetry.EcalLaserSorting.LmfSource_cfi")11#ECAL Data dump (dumpRaw)12#process.load("pgras.DumpRaw.DumpRaw_cfi")13#process.dumpRaw.dump = cms.untracked.bool(False) 14process.source.fileNames = [ "/localdata/disk0/craft1-sorting-new/out/EB-1/Run66079_LB0001.lmf" ]15process.Timing = cms.Service("Timing")16process.load("EventFilter.EcalRawToDigi.EcalUnpackerMapping_cfi")17process.load("EventFilter.EcalRawToDigi.EcalUnpackerData_cfi")18process.ecalEBunpacker.silentMode = cms.untracked.bool(True)19process.load("Geometry.EcalMapping.EcalMapping_cfi")20process.load("Geometry.EcalMapping.EcalMappingRecord_cfi")21#import EventFilter.ESRawToDigi.esRawToDigi_cfi...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful