Best Syzkaller code snippet using ipcconfig.Default
testing.go
Source:testing.go
1// Copyright 2017 syzkaller project authors. All rights reserved.2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.3package main4import (5 "fmt"6 "io/ioutil"7 "strings"8 "time"9 "github.com/google/syzkaller/pkg/csource"10 "github.com/google/syzkaller/pkg/host"11 "github.com/google/syzkaller/pkg/ipc"12 "github.com/google/syzkaller/pkg/log"13 "github.com/google/syzkaller/pkg/osutil"14 "github.com/google/syzkaller/pkg/rpctype"15 "github.com/google/syzkaller/pkg/runtest"16 "github.com/google/syzkaller/prog"17)18type checkArgs struct {19 target *prog.Target20 sandbox string21 gitRevision string22 targetRevision string23 enabledCalls []int24 allSandboxes bool25 ipcConfig *ipc.Config26 ipcExecOpts *ipc.ExecOpts27 featureFlags map[string]csource.Feature28}29func testImage(hostAddr string, args *checkArgs) {30 log.Logf(0, "connecting to host at %v", hostAddr)31 conn, err := rpctype.Dial(hostAddr, args.ipcConfig.Timeouts.Scale)32 if err != nil {33 log.Fatalf("BUG: failed to connect to host: %v", err)34 }35 conn.Close()36 if _, err := checkMachine(args); err != nil {37 log.Fatalf("BUG: %v", err)38 }39}40func runTest(target *prog.Target, manager *rpctype.RPCClient, name, executor string) {41 pollReq := &rpctype.RunTestPollReq{Name: name}42 for {43 req := new(rpctype.RunTestPollRes)44 if err := manager.Call("Manager.Poll", pollReq, req); err != nil {45 log.Fatalf("Manager.Poll call failed: %v", err)46 }47 if len(req.Bin) == 0 && len(req.Prog) == 0 {48 return49 }50 test := convertTestReq(target, req)51 if test.Err == nil {52 runtest.RunTest(test, executor)53 }54 reply := &rpctype.RunTestDoneArgs{55 Name: name,56 ID: req.ID,57 Output: test.Output,58 Info: test.Info,59 }60 if test.Err != nil {61 reply.Error = test.Err.Error()62 }63 if err := manager.Call("Manager.Done", reply, nil); err != nil {64 log.Fatalf("Manager.Done call failed: %v", err)65 }66 }67}68func convertTestReq(target *prog.Target, req *rpctype.RunTestPollRes) *runtest.RunRequest {69 test := &runtest.RunRequest{70 Cfg: req.Cfg,71 Opts: req.Opts,72 Repeat: req.Repeat,73 }74 if len(req.Bin) != 0 {75 bin, err := osutil.TempFile("syz-runtest")76 if err != nil {77 test.Err = err78 return test79 }80 if err := osutil.WriteExecFile(bin, req.Bin); err != nil {81 test.Err = err82 return test83 }84 test.Bin = bin85 }86 if len(req.Prog) != 0 {87 p, err := target.Deserialize(req.Prog, prog.NonStrict)88 if err != nil {89 test.Err = err90 return test91 }92 test.P = p93 }94 return test95}96func checkMachineHeartbeats(done chan bool) {97 ticker := time.NewTicker(3 * time.Second)98 defer ticker.Stop()99 for {100 select {101 case <-done:102 return103 case <-ticker.C:104 fmt.Printf("executing program\n")105 }106 }107}108func checkMachine(args *checkArgs) (*rpctype.CheckArgs, error) {109 log.Logf(0, "checking machine...")110 // Machine checking can be very slow on some machines (qemu without kvm, KMEMLEAK linux, etc),111 // so print periodic heartbeats for vm.MonitorExecution so that it does not decide that we are dead.112 done := make(chan bool)113 defer close(done)114 go checkMachineHeartbeats(done)115 if err := checkRevisions(args); err != nil {116 return nil, err117 }118 globFiles, err := host.CollectGlobsInfo(args.target.GetGlobs())119 if err != nil {120 return nil, fmt.Errorf("failed to collect glob info: %v", err)121 }122 // TODO: make host.DetectSupportedSyscalls below filter out globs with no values.123 // Also make prog package more strict with respect to generation/mutation of globs124 // with no values (they still can appear in tests and tools). We probably should125 // generate an empty string for these and never mutate.126 args.target.UpdateGlobs(globFiles)127 features, err := host.Check(args.target)128 if err != nil {129 return nil, err130 }131 if feat := features[host.FeatureCoverage]; !feat.Enabled &&132 args.ipcConfig.Flags&ipc.FlagSignal != 0 {133 return nil, fmt.Errorf("coverage is not supported (%v)", feat.Reason)134 }135 if feat := features[host.FeatureSandboxSetuid]; !feat.Enabled &&136 args.ipcConfig.Flags&ipc.FlagSandboxSetuid != 0 {137 return nil, fmt.Errorf("sandbox=setuid is not supported (%v)", feat.Reason)138 }139 if feat := features[host.FeatureSandboxNamespace]; !feat.Enabled &&140 args.ipcConfig.Flags&ipc.FlagSandboxNamespace != 0 {141 return nil, fmt.Errorf("sandbox=namespace is not supported (%v)", feat.Reason)142 }143 if feat := features[host.FeatureSandboxAndroid]; !feat.Enabled &&144 args.ipcConfig.Flags&ipc.FlagSandboxAndroid != 0 {145 return nil, fmt.Errorf("sandbox=android is not supported (%v)", feat.Reason)146 }147 createIPCConfig(features, args.ipcConfig)148 if err := checkSimpleProgram(args, features); err != nil {149 return nil, err150 }151 res := &rpctype.CheckArgs{152 Features: features,153 EnabledCalls: make(map[string][]int),154 DisabledCalls: make(map[string][]rpctype.SyscallReason),155 GlobFiles: globFiles,156 }157 if err := checkCalls(args, res); err != nil {158 return nil, err159 }160 return res, nil161}162func checkCalls(args *checkArgs, res *rpctype.CheckArgs) error {163 sandboxes := []string{args.sandbox}164 if args.allSandboxes {165 if args.sandbox != "none" {166 sandboxes = append(sandboxes, "none")167 }168 if args.sandbox != "setuid" && res.Features[host.FeatureSandboxSetuid].Enabled {169 sandboxes = append(sandboxes, "setuid")170 }171 if args.sandbox != "namespace" && res.Features[host.FeatureSandboxNamespace].Enabled {172 sandboxes = append(sandboxes, "namespace")173 }174 // TODO: Add "android" sandbox here when needed. Will require fixing runtests.175 }176 for _, sandbox := range sandboxes {177 enabledCalls, disabledCalls, err := buildCallList(args.target, args.enabledCalls, sandbox)178 res.EnabledCalls[sandbox] = enabledCalls179 res.DisabledCalls[sandbox] = disabledCalls180 if err != nil {181 return err182 }183 }184 if args.allSandboxes {185 var enabled []int186 for _, id := range res.EnabledCalls["none"] {187 switch args.target.Syscalls[id].Name {188 default:189 enabled = append(enabled, id)190 case "syz_emit_ethernet", "syz_extract_tcp_res":191 // Tun is not setup without sandbox, this is a hacky way to workaround this.192 }193 }194 res.EnabledCalls[""] = enabled195 }196 return nil197}198func checkRevisions(args *checkArgs) error {199 log.Logf(0, "checking revisions...")200 executorArgs := strings.Split(args.ipcConfig.Executor, " ")201 executorArgs = append(executorArgs, "version")202 cmd := osutil.Command(executorArgs[0], executorArgs[1:]...)203 cmd.Stderr = ioutil.Discard204 if _, err := cmd.StdinPipe(); err != nil { // for the case executor is wrapped with ssh205 return err206 }207 out, err := osutil.Run(time.Minute, cmd)208 if err != nil {209 return fmt.Errorf("failed to run executor version: %v", err)210 }211 vers := strings.Split(strings.TrimSpace(string(out)), " ")212 if len(vers) != 4 {213 return fmt.Errorf("executor version returned bad result: %q", string(out))214 }215 if args.target.Arch != vers[1] {216 return fmt.Errorf("mismatching target/executor arches: %v vs %v", args.target.Arch, vers[1])217 }218 if prog.GitRevision != vers[3] {219 return fmt.Errorf("mismatching fuzzer/executor git revisions: %v vs %v",220 prog.GitRevision, vers[3])221 }222 if args.gitRevision != prog.GitRevision {223 return fmt.Errorf("mismatching manager/fuzzer git revisions: %v vs %v",224 args.gitRevision, prog.GitRevision)225 }226 if args.target.Revision != vers[2] {227 return fmt.Errorf("mismatching fuzzer/executor system call descriptions: %v vs %v",228 args.target.Revision, vers[2])229 }230 if args.target.Revision != args.targetRevision {231 return fmt.Errorf("mismatching fuzzer/manager system call descriptions: %v vs %v",232 args.target.Revision, args.targetRevision)233 }234 return nil235}236func checkSimpleProgram(args *checkArgs, features *host.Features) error {237 log.Logf(0, "testing simple program...")238 if err := host.Setup(args.target, features, args.featureFlags, args.ipcConfig.Executor); err != nil {239 return fmt.Errorf("host setup failed: %v", err)240 }241 env, err := ipc.MakeEnv(args.ipcConfig, 0, "")242 if err != nil {243 return fmt.Errorf("failed to create ipc env: %v", err)244 }245 defer env.Close()246 p := args.target.DataMmapProg()247 output, info, hanged, err := env.Exec(args.ipcExecOpts, p)248 if err != nil {249 return fmt.Errorf("program execution failed: %v\n%s", err, output)250 }251 if hanged {252 return fmt.Errorf("program hanged:\n%s", output)253 }254 if len(info.Calls) == 0 {255 return fmt.Errorf("no calls executed:\n%s", output)256 }257 if info.Calls[0].Errno != 0 {258 return fmt.Errorf("simple call failed: %+v\n%s", info.Calls[0], output)259 }260 if args.ipcConfig.Flags&ipc.FlagSignal != 0 && len(info.Calls[0].Signal) < 2 {261 return fmt.Errorf("got no coverage:\n%s", output)262 }263 if len(info.Calls[0].Signal) < 1 {264 return fmt.Errorf("got no fallback coverage:\n%s", output)265 }266 return nil267}268func buildCallList(target *prog.Target, enabledCalls []int, sandbox string) (269 enabled []int, disabled []rpctype.SyscallReason, err error) {270 log.Logf(0, "building call list...")271 calls := make(map[*prog.Syscall]bool)272 if len(enabledCalls) != 0 {273 for _, n := range enabledCalls {274 if n >= len(target.Syscalls) {275 return nil, nil, fmt.Errorf("unknown enabled syscall %v", n)276 }277 calls[target.Syscalls[n]] = true278 }279 } else {280 for _, c := range target.Syscalls {281 calls[c] = true282 }283 }284 _, unsupported, err := host.DetectSupportedSyscalls(target, sandbox, calls)285 if err != nil {286 return nil, nil, fmt.Errorf("failed to detect host supported syscalls: %v", err)287 }288 for c := range calls {289 if reason, ok := unsupported[c]; ok {290 log.Logf(1, "unsupported syscall: %v: %v", c.Name, reason)291 disabled = append(disabled, rpctype.SyscallReason{292 ID: c.ID,293 Reason: reason,294 })295 delete(calls, c)296 }297 }298 _, unsupported = target.TransitivelyEnabledCalls(calls)299 for c := range calls {300 if reason, ok := unsupported[c]; ok {301 log.Logf(1, "transitively unsupported: %v: %v", c.Name, reason)302 disabled = append(disabled, rpctype.SyscallReason{303 ID: c.ID,304 Reason: reason,305 })306 delete(calls, c)307 }308 }309 for c := range calls {310 enabled = append(enabled, c.ID)311 }312 if len(calls) == 0 {313 return enabled, disabled, fmt.Errorf("all system calls are disabled")314 }315 return enabled, disabled, nil316}...
security.go
Source:security.go
...84 if err != nil {85 return err86 }87 } else {88 mergedCaps, err := capabilities.MergeCapabilities(rtc.Containers.DefaultCapabilities, s.CapAdd, s.CapDrop)89 if err != nil {90 return err91 }92 boundingSet, err := capabilities.BoundingSet()93 if err != nil {94 return err95 }96 boundingCaps := make(map[string]interface{})97 for _, b := range boundingSet {98 boundingCaps[b] = b99 }100 for _, c := range mergedCaps {101 if _, ok := boundingCaps[c]; ok {102 caplist = append(caplist, c)103 }104 }105 privCapsRequired := []string{}106 // If the container image specifies an label with a107 // capabilities.ContainerImageLabel then split the comma separated list108 // of capabilities and record them. This list indicates the only109 // capabilities, required to run the container.110 var capsRequiredRequested []string111 for key, val := range s.Labels {112 if util.StringInSlice(key, capabilities.ContainerImageLabels) {113 capsRequiredRequested = strings.Split(val, ",")114 }115 }116 if !s.Privileged && len(capsRequiredRequested) > 0 {117 // Pass capRequiredRequested in CapAdd field to normalize capabilities names118 capsRequired, err := capabilities.MergeCapabilities(nil, capsRequiredRequested, nil)119 if err != nil {120 return errors.Wrapf(err, "capabilities requested by user or image are not valid: %q", strings.Join(capsRequired, ","))121 }122 // Verify all capRequired are in the capList123 for _, cap := range capsRequired {124 if !util.StringInSlice(cap, caplist) {125 privCapsRequired = append(privCapsRequired, cap)126 }127 }128 if len(privCapsRequired) == 0 {129 caplist = capsRequired130 } else {131 logrus.Errorf("Capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ","))132 }133 }134 }135 configSpec := g.Config136 configSpec.Process.Capabilities.Ambient = []string{}137 // Always unset the inheritable capabilities similarly to what the Linux kernel does138 // They are used only when using capabilities with uid != 0.139 configSpec.Process.Capabilities.Inheritable = []string{}140 configSpec.Process.Capabilities.Bounding = caplist141 user := strings.Split(s.User, ":")[0]142 if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" {143 configSpec.Process.Capabilities.Effective = caplist144 configSpec.Process.Capabilities.Permitted = caplist145 } else {146 mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil)147 if err != nil {148 return errors.Wrapf(err, "capabilities requested by user are not valid: %q", strings.Join(s.CapAdd, ","))149 }150 boundingSet, err := capabilities.BoundingSet()151 if err != nil {152 return err153 }154 boundingCaps := make(map[string]interface{})155 for _, b := range boundingSet {156 boundingCaps[b] = b157 }158 var userCaps []string159 for _, c := range mergedCaps {160 if _, ok := boundingCaps[c]; ok {161 userCaps = append(userCaps, c)162 }163 }164 configSpec.Process.Capabilities.Effective = userCaps165 configSpec.Process.Capabilities.Permitted = userCaps166 // Ambient capabilities were added to Linux 4.3. Set ambient167 // capabilities only when the kernel supports them.168 if supportAmbientCapabilities() {169 configSpec.Process.Capabilities.Ambient = userCaps170 configSpec.Process.Capabilities.Inheritable = userCaps171 }172 }173 g.SetProcessNoNewPrivileges(s.NoNewPrivileges)174 if err := setupApparmor(s, rtc, g); err != nil {175 return err176 }177 // HANDLE SECCOMP178 if s.SeccompProfilePath != "unconfined" {179 seccompConfig, err := getSeccompConfig(s, configSpec, newImage)180 if err != nil {181 return err182 }183 configSpec.Linux.Seccomp = seccompConfig184 }185 // Clear default Seccomp profile from Generator for unconfined containers186 // and privileged containers which do not specify a seccomp profile.187 if s.SeccompProfilePath == "unconfined" || (s.Privileged && (s.SeccompProfilePath == "" || s.SeccompProfilePath == config.SeccompOverridePath || s.SeccompProfilePath == config.SeccompDefaultPath)) {188 configSpec.Linux.Seccomp = nil189 }190 g.SetRootReadonly(s.ReadOnlyFilesystem)191 noUseIPC := s.IpcNS.NSMode == specgen.FromContainer || s.IpcNS.NSMode == specgen.FromPod || s.IpcNS.NSMode == specgen.Host192 noUseNet := s.NetNS.NSMode == specgen.FromContainer || s.NetNS.NSMode == specgen.FromPod || s.NetNS.NSMode == specgen.Host193 noUseUTS := s.UtsNS.NSMode == specgen.FromContainer || s.UtsNS.NSMode == specgen.FromPod || s.UtsNS.NSMode == specgen.Host194 // Add default sysctls195 defaultSysctls, err := util.ValidateSysctls(rtc.Sysctls())196 if err != nil {197 return err198 }199 for sysctlKey, sysctlVal := range defaultSysctls {200 // Ignore mqueue sysctls if --ipc=host201 if noUseIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {...
config.go
Source:config.go
...65 if err != nil {66 return config, err67 }68 }69 config.SeeleConfig.TxConf = *core.DefaultTxPoolConfig()70 config.SeeleConfig.GenesisConfig = cmdConfig.GenesisConfig71 comm.LogConfiguration.PrintLog = config.LogConfig.PrintLog72 comm.LogConfiguration.IsDebug = config.LogConfig.IsDebug73 comm.LogConfiguration.DataDir = config.BasicConfig.DataDir74 config.BasicConfig.DataDir = filepath.Join(common.GetDefaultDataFolder(), config.BasicConfig.DataDir)75 config.BasicConfig.DataSetDir = filepath.Join(common.GetTempFolder(), config.BasicConfig.DataDir)76 return config, nil77}78// convertIPCServerPath convert the config to the real path79func convertIPCServerPath(cmdConfig *util.Config, config *node.Config) {80 if cmdConfig.Ipcconfig.PipeName == "" {81 config.IpcConfig.PipeName = common.GetDefaultIPCPath()82 } else if runtime.GOOS == "windows" {83 config.IpcConfig.PipeName = common.WindowsPipeDir + cmdConfig.Ipcconfig.PipeName84 } else {85 config.IpcConfig.PipeName = filepath.Join(common.GetDefaultDataFolder(), cmdConfig.Ipcconfig.PipeName)86 }87}88// CopyConfig copy Config from the given config89func CopyConfig(cmdConfig *util.Config) *node.Config {90 config := &node.Config{91 BasicConfig: cmdConfig.BasicConfig,92 LogConfig: cmdConfig.LogConfig,93 HTTPServer: cmdConfig.HTTPServer,94 WSServerConfig: cmdConfig.WSServerConfig,95 P2PConfig: cmdConfig.P2PConfig,96 SeeleConfig: node.SeeleConfig{},97 MetricsConfig: cmdConfig.MetricsConfig,98 }99 return config...
Default
Using AI Code Generation
1import (2func main() {3 ipc := p2p.IpcEndpoint("test.ipc")4 fmt.Println("IpcEndpoint:", ipc)5 tcp := p2p.TCPEndpoint(30303)6 fmt.Println("TCPEndpoint:", tcp)7 udp := p2p.UDPEndpoint(30303)8 fmt.Println("UDPEndpoint:", udp)9 ws := p2p.WSEndpoint("localhost:8546")10 fmt.Println("WSEndpoint:", ws)11 wss := p2p.WSSEndpoint("localhost:8546")12 fmt.Println("WSSEndpoint:", wss)13 discv5 := discv5.NewEndpoint(30303)14 fmt.Println("NewEndpoint:", discv5)15 nat := nat.Any()16 fmt.Println("Any:", nat)17 netutil := netutil.LimitListener(netutil.DummyListener(1), 1)18 fmt.Println("LimitListener:", netutil)19 adapters := adapters.NewSimAdapter(nil)20 fmt.Println("NewSimAdapter:", adapters)21}22IpcEndpoint: &{test.ipc}23TCPEndpoint: &{30303}24UDPEndpoint: &{30303}25WSEndpoint: &{localhost:8546}26WSSEndpoint: &{localhost:8546}27NewEndpoint: &{30303}28Any: &{0xc0000b4120}29LimitListener: &{0xc0000b4140}30NewSimAdapter: &{0xc0000b4160}
Default
Using AI Code Generation
1import (2func main() {3 conn, err := ethclient.Dial("/Users/username/Library/Ethereum/geth.ipc")4 if err != nil {5 log.Fatalf("Failed to connect to the Ethereum client: %v", err)6 }7 header, err := conn.HeaderByNumber(context.Background(), nil)8 if err != nil {9 log.Fatalf("Failed to retrieve header: %v", err)10 }11 fmt.Println(header.Number)12}13import (14func main() {15 if err != nil {16 log.Fatalf("Failed to connect to the Ethereum client: %v", err)17 }18 header, err := conn.HeaderByNumber(context.Background(), nil)19 if err != nil {20 log.Fatalf("Failed to retrieve header: %v", err)21 }22 fmt.Println(header.Number)23}24import (25func main() {26 if err != nil {27 log.Fatalf("Failed to connect to the Ethereum client: %v", err)28 }
Default
Using AI Code Generation
1import (2func main() {3 client, err := ethclient.Dial(ipcEndpoint)4 if err != nil {5 log.Fatalf("Failed to connect to the Ethereum client: %v", err)6 }7 fmt.Println("Connected to Ethereum client")8}9import (10func main() {11 ipcClient, err := ipc.Dial(ipcEndpoint)12 if err != nil {13 log.Fatalf("Failed to connect to the Ethereum client: %v", err)14 }15 client := ethclient.NewClient(ipcClient)16 fmt.Println("Connected to Ethereum client")17}18import (19func main() {20 httpclient, err := rpc.Dial(httpEndpoint)21 if err != nil {22 log.Fatalf("Failed to connect to the Ethereum client: %v", err)23 }24 client := ethclient.NewClient(httpclient)25 fmt.Println("Connected to Ethereum client")26}27import (28func main() {
Default
Using AI Code Generation
1import (2func main() {3 client, err := ipcconfig.Default()4 if err != nil {5 log.Fatal(err)6 }7 rpcClient, err := rpc.Dial(client.IPCPath)8 if err != nil {9 log.Fatal(err)10 }11 ethClient := ethclient.NewClient(rpcClient)12 blockNumber, err := ethClient.BlockNumber()13 if err != nil {14 log.Fatal(err)15 }16 fmt.Println("Block Number: ", blockNumber)17}18import (19func main() {20 client, err := ipcconfig.Custom("/home/ethereum/.ethereum/geth.ipc")21 if err != nil {22 log.Fatal(err)23 }24 rpcClient, err := rpc.Dial(client.IPCPath)25 if err != nil {26 log.Fatal(err)27 }28 ethClient := ethclient.NewClient(rpcClient)29 blockNumber, err := ethClient.BlockNumber()30 if err != nil {31 log.Fatal(err)32 }33 fmt.Println("Block Number: ", blockNumber)34}35import (36func main() {37 client, err := ipcconfig.Custom("/home/ethereum/.ethereum/geth.ipc")38 if err != nil {39 log.Fatal(err)40 }41 rpcClient, err := rpc.Dial(client.IPCPath)42 if err != nil {43 log.Fatal(err)44 }
Default
Using AI Code Generation
1import (2func main() {3 ipc := params.IpcConfig{Enabled: true}4 fmt.Println(ipc.Default())5}6import (7func main() {8 ipc := params.IpcConfig{Enabled: false}9 fmt.Println(ipc.Default())10}
Default
Using AI Code Generation
1import "fmt"2import "ipcconfig"3func main() {4 fmt.Println("main method")5 ipcconfig.Default()6}7import "fmt"8func Default() {9 fmt.Println("Default method")10}11We can import the ipcconfig package in 2.go file as shown below:12import "fmt"13import "ipcconfig"14func main() {15 fmt.Println("main method")16 ipcconfig.Default()17}18import "fmt"19func Default() {20 fmt.Println("Default method")21}22In the above example, we have used Default() function of ipcconfig package in main package. We can also use Default() function in ipcconfig package itself as shown below:23import "fmt"24import "ipcconfig"25func main() {26 fmt.Println("main method")27 ipcconfig.Default()28}29import "fmt"30func Default() {31 fmt.Println("Default method")32 Default()33}34The reason is that we are trying to call Default() function in ipcconfig package from Default() function
Default
Using AI Code Generation
1import (2func main() {3 fmt.Println("Enter the number of IPCs")4 fmt.Scanln(&n)5 fmt.Println("Enter the IPCs")6 ipc := make([]string, n)7 for i := 0; i < n; i++ {8 fmt.Scanln(&ipc[i])9 }10 ipcconfig.Default(ipc)11}12import (13func Default(ipc []string) []string {14 ipc = append(ipc, "
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!