How to use converge method in molecule

Best Python code snippet using molecule_python

cases.py

Source:cases.py Github

copy

Full Screen

...255 pgs[_(2)].connect(256 acts[_(2)],257 acts[_(3)],258 acts[_(4)]259 ).converge(cgs[_(1)]).extend(acts[_(7)]).extend(egs[_(1)]).connect(260 pgs[_(2)],261 cgs[_(3)]262 )263 acts[_(5)].extend(egs[_(7)]).connect(264 cgs[_(3)],265 acts[_(8)]266 ).to(acts[_(8)]).extend(egs[_(8)]).connect(267 acts[_(8)],268 acts[_(11)]269 ).to(acts[_(11)]).extend(cgs[_(3)])270 acts[_(6)].extend(egs[_(2)]).connect(271 acts[_(9)],272 acts[_(10)],273 ).converge(cgs[_(2)]).extend(acts[_(12)]).extend(egs[_(6)]).connect(274 acts[_(6)],275 cgs[_(3)],276 cgs[_(2)]277 ).to(egs[_(2)]).connect(acts[_(6)])278 cgs[_(3)].extend(acts[_(13)]).extend(egs[_(3)]).connect(279 end,280 acts[_(14)],281 pgs[_(3)],282 acts[_(1)]283 )284 acts[_(14)].extend(egs[_(4)]).connect(285 acts[_(13)],286 cgs[_(4)]287 )288 pgs[_(3)].connect(289 acts[_(15)],290 acts[_(16)],291 acts[_(17)]292 ).to(acts[_(15)]).extend(acts[_(18)]).extend(cgs[_(4)]) \293 .to(acts[_(17)]).extend(egs[_(5)]).connect(294 acts[_(19)],295 acts[_(20)]296 ).to(acts[_(19)]).extend(cgs[_(4)]).to(acts[_(20)]).extend(cgs[_(4)]) \297 .to(acts[_(16)]).extend(cgs[_(4)]).extend(end)298 for node in nodes:299 a = outgoing_assert[node.id]300 out = {out.id for out in node.outgoing}301 testcase.assertEqual(a['len'], len(node.outgoing),302 msg='{id} actual: {a}, expect: {e}'.format(id=node.id, a=len(node.outgoing), e=a['len']))303 testcase.assertEqual(a['outgoing'], out,304 msg='{id} actual: {a}, expect: {e}'.format(id=node.id, a=out, e=a['outgoing']))305 return build_tree(start), gateway_validation_assert, stream_assert306def flow_valid_edge_case_1():307 start = EmptyStartEvent(id=start_event_id)308 act_1 = ServiceActivity(id=act_id(1))309 act_2 = ServiceActivity(id=act_id(2))310 eg = ExclusiveGateway(id=exclusive_gw_id(1), conditions={311 0: '123',312 1: '456',313 2: '789'314 })315 act_3 = ServiceActivity(id=act_id(3))316 end = EmptyEndEvent(id=end_event_id)317 start.extend(act_1).extend(act_2).extend(eg).connect(318 act_1,319 act_2,320 act_3321 ).to(act_3).extend(end)322 return build_tree(start)323def flow_valid_edge_case_2():324 return {325 'activities': {326 'act_1': {'component': {'inputs': {}, 'code': None}, 'outgoing': '82b12b6aae533e55bdcc5bccfb014c2d',327 'incoming': ['3fc89273786a36b8a6e7beac8301274d'], 'name': None, 'error_ignorable': False,328 'type': 'ServiceActivity', 'id': 'act_1', 'optional': False},329 'act_2': {'component': {'inputs': {}, 'code': None}, 'outgoing': '3368add44347310eaef1f26f25909026',330 'incoming': ['76caeed0e6053fea9db84a89f56a74a8'], 'name': None, 'error_ignorable': False,331 'type': 'ServiceActivity', 'id': 'act_2', 'optional': False}},332 'end_event': {'type': 'EmptyEndEvent', 'outgoing': '', 'incoming': ['05f91b45a15b37d7b0c96d3ff94bff80'],333 'id': 'end_event_id', 'name': None},334 'flows': {335 '27a9cdeaef623d37834ac6917d05eac5': {'is_default': False, 'source': 'start_event_id', 'target': 'pg_1',336 'id': '27a9cdeaef623d37834ac6917d05eac5'},337 '82b12b6aae533e55bdcc5bccfb014c2d': {'is_default': False, 'source': 'act_1', 'target': 'cg_1',338 'id': '82b12b6aae533e55bdcc5bccfb014c2d'},339 '3368add44347310eaef1f26f25909026': {'is_default': False, 'source': 'act_2', 'target': 'cg_1',340 'id': '3368add44347310eaef1f26f25909026'},341 '05f91b45a15b37d7b0c96d3ff94bff80': {'is_default': False, 'source': 'cg_1', 'target': 'end_event_id',342 'id': '05f91b45a15b37d7b0c96d3ff94bff80'},343 '3fc89273786a36b8a6e7beac8301274d': {'is_default': False, 'source': 'pg_1', 'target': 'act_1',344 'id': '3fc89273786a36b8a6e7beac8301274d'},345 '76caeed0e6053fea9db84a89f56a74a8': {'is_default': False, 'source': 'pg_1', 'target': 'act_2',346 'id': '76caeed0e6053fea9db84a89f56a74a8'},347 '76casdgd0e6053ea9db84a89f56a1234': {'is_default': False, 'source': 'pg_1', 'target': 'cg_1',348 'id': '76caeed0e6053fea9db84a89f56a74a8'}},349 'gateways': {350 'cg_1': {'type': 'ConvergeGateway', 'outgoing': '05f91b45a15b37d7b0c96d3ff94bff80',351 'incoming': ['82b12b6aae533e55bdcc5bccfb014c2d',352 '3368add44347310eaef1f26f25909026',353 '76casdgd0e6053ea9db84a89f56a1234'], 'id': 'cg_1',354 'name': None},355 'pg_1': {'outgoing': ['3fc89273786a36b8a6e7beac8301274d',356 '76caeed0e6053fea9db84a89f56a74a8',357 '76casdgd0e6053ea9db84a89f56a1234'],358 'incoming': ['27a9cdeaef623d37834ac6917d05eac5'], 'name': None, 'converge_gateway_id': 'cg_1',359 'type': 'ParallelGateway', 'id': 'pg_1'}},360 'start_event': {'type': 'EmptyStartEvent', 'outgoing': '27a9cdeaef623d37834ac6917d05eac5', 'incoming': '',361 'id': 'start_event_id', 'name': None}, 'data': {'inputs': {}, 'outputs': {}},362 'id': 'c986802cd1e23a5f920c85b005f16dc3'}363def flow_invalid_case_1():364 start = EmptyStartEvent(id=start_event_id)365 act_1 = ServiceActivity(id=act_id(1))366 pg = ParallelGateway(id=parallel_gw_id(1))367 act_2 = ServiceActivity(id=act_id(2))368 act_3 = ServiceActivity(id=act_id(3))369 eg = ExclusiveGateway(id=exclusive_gw_id(1), conditions={370 0: '123',371 1: '456'372 })373 act_4 = ServiceActivity(id=act_id(4))374 cg = ConvergeGateway(id=converge_gw_id(1))375 end = EmptyEndEvent(id=end_event_id)376 start.extend(act_1).extend(pg).connect(377 act_2,378 act_3,379 eg380 ).to(eg).connect(381 act_3,382 act_4383 )384 act_2.connect(cg)385 act_3.connect(cg)386 act_4.connect(cg)387 cg.extend(end)388 return build_tree(start)389def flow_invalid_case_2():390 start = EmptyStartEvent(id=start_event_id)391 act_1 = ServiceActivity(id=act_id(1))392 eg = ExclusiveGateway(id=exclusive_gw_id(1), conditions={393 0: '123',394 1: '456'395 })396 act_2 = ServiceActivity(id=act_id(2))397 pg = ParallelGateway(id=parallel_gw_id(1))398 act_3 = ServiceActivity(id=act_id(3))399 act_4 = ServiceActivity(id=act_id(4))400 cg = ConvergeGateway(id=converge_gw_id(1))401 end = EmptyEndEvent(id=end_event_id)402 start.extend(act_1).extend(eg).connect(403 act_3,404 act_2405 ).to(act_2).extend(pg).connect(406 act_3,407 act_4408 ).converge(cg).extend(end)409 return build_tree(start)410flow_valid_edge_cases = [411 {412 'case': flow_valid_edge_case_1,413 },414 {415 'case': flow_valid_edge_case_2,416 }417]418flow_invalid_cases = [419 {420 'case': flow_invalid_case_1,421 'assert_invalid': act_id(3)422 },...

Full Screen

Full Screen

package.py

Source:package.py Github

copy

Full Screen

1# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other2# Spack Project Developers. See the top-level COPYRIGHT file for details.3#4# SPDX-License-Identifier: (Apache-2.0 OR MIT)5import glob6import os7from spack import *8class Converge(Package):9 """CONVERGE is a revolutionary computational fluid dynamics (CFD) program10 that eliminates the grid generation bottleneck from the simulation process.11 CONVERGE was developed by engine simulation experts and is straightforward12 to use for both engine and non-engine simulations. Unlike many CFD13 programs, CONVERGE automatically generates a perfectly orthogonal,14 structured grid at runtime based on simple, user-defined grid control15 parameters. This grid generation method completely eliminates the need to16 manually generate a grid. In addition, CONVERGE offers many other features17 to expedite the setup process and to ensure that your simulations are as18 computationally efficient as possible."""19 homepage = "https://www.convergecfd.com/"20 url = "https://download.convergecfd.com/download/CONVERGE_2.4/Full_Solver_Packages/converge_install_2.4.10.tar.gz"21 # In order to view available versions, you need to register for an account:22 # https://download.convergecfd.com/wp-login.php?action=register23 version('2.4.10', sha256='5d3c39894598d2395149cfcc653af13b8b1091177290edd62fcf22c7e830d410')24 version('2.3.23', sha256='1217d16eaf9d263f917ee468778508bad9dacb7e4397a293cfa6467f39fb4c52')25 version('2.2.0', sha256='3885acbaf352c718ea69f0206c858a01be02f0928ffee738e4aceb1dd939a77a',26 url="https://download.convergecfd.com/download/CONVERGE_2.2/Full_Solver_Packages/converge_install_2.2.0_042916.tar.gz")27 version('2.1.0', sha256='6b8896d42cf7b9013cae5456f4dc118306a5bd271d4a15945ceb7dae913e825a',28 url="https://download.convergecfd.com/download/CONVERGE_2.1/Full_Solver_Packages/converge_install_2.1.0_111615.tar.gz")29 version('2.0.0', sha256='f32c4824eb33724d85e283481d67ebd0630b1406011c528d775028bb2546f34e',30 url="https://download.convergecfd.com/download/CONVERGE_2.0/Full_Solver_Packages/converge_install_2.0.0_090214.tar.gz")31 variant('mpi', default=True, description='Build with MPI support')32 # The following MPI libraries are compatible with CONVERGE:33 #34 # +--------------+---------+---------+---------+---------+---------+35 # | MPI Packages | v2.0 | v2.1 | v2.2 | v2.3 | v2.4 |36 # +--------------+---------+---------+---------+---------+---------+37 # | HP-MPI | 2.0.3+ | 2.0.3+ | 2.0.3+ | 2.0.3+ | |38 # | Intel MPI | | | | | 17.0.98 |39 # | MPICH | ?.?.? | ?.?.? | 1.2.1 | 3.1.4 | ?.?.? |40 # | MVAPICH2 | ?.?.? | | | | |41 # | Open MPI | 1.0-1.4 | 1.0-1.4 | 1.5-1.8 | 1.5-1.8 | 1.10 |42 # | Platform MPI | | | 9.1.2 | 9.1.2 | 9.1.2 |43 # +--------------+---------+---------+---------+---------+---------+44 #45 # NOTE: HP-MPI was bought out by Platform MPI46 #47 # These version requirements are more strict than for most packages.48 # Since the tarball comes with pre-compiled executables,49 # the version of libmpi.so must match exactly, or else50 # you will end up with missing libraries and symbols.51 depends_on('mpi', when='+mpi')52 # FIXME: Concretization is currently broken, so this causes:53 # $ spack spec converge54 # to crash. You must explicitly state what MPI version you want:55 # $ spack spec converge@2.4.10 +mpi ^openmpi@:1.1056 #57 # TODO: Add version ranges for other MPI libraries58 depends_on('openmpi@1.10.0:1.10.999', when='@2.4.0:2.4.999+mpi^openmpi')59 depends_on('openmpi@1.5:1.8', when='@2.2:2.3+mpi^openmpi')60 depends_on('openmpi@:1.4', when='@:2.1+mpi^openmpi')61 # TODO: Add packages for hp-mpi and platform-mpi62 # conflicts('^hp-mpi', when='@2.4:')63 conflicts('^intel-mpi', when='@:2.3')64 conflicts('^intel-parallel-studio+mpi', when='@:2.3')65 # conflicts('^platform-mpi', when='@:2.1')66 conflicts('^spectrum-mpi')67 # Licensing68 license_required = True69 license_comment = '#'70 license_files = ['license/license.lic']71 license_vars = ['RLM_LICENSE']72 license_url = 'http://www.reprisesoftware.com/RLM_License_Administration.pdf'73 def url_for_version(self, version):74 url = "https://download.convergecfd.com/download/CONVERGE_{0}/Full_Solver_Packages/converge_install_{1}.tar.gz"75 return url.format(version.up_to(2), version)76 def install(self, spec, prefix):77 # 2.0.078 # converge -> converge-2.0.0-hpmpi-09021479 # converge-2.0.0-hpmpi-090214 -> libmpi.so.1, libmpio.so.180 # converge-2.0.0-mpich2-090214 -> libmpich.so.1.281 # converge-2.0.0-mvapich-090214 -> libibumad.so.182 # converge-2.0.0-openmpi-090214 -> libmpi.so.083 # converge-2.0.0-serial-09021484 # make_surface85 # post_convert86 # 2.1.087 # converge -> converge-2.1.0-hpmpi-11161588 # converge-2.1.0-hpmpi-111615 -> libmpi.so.1, libmpio.so.189 # converge-2.1.0-mpich2-111615 -> libmpich.so.1.290 # converge-2.1.0-openmpi-111615 -> libmpi.so.091 # converge-2.1.0-serial-11161592 # make_surface93 # post_convert94 # 2.2.095 # converge -> converge-2.2.0-hpmpi-04291696 # converge-2.2.0-hpmpi-042916 -> libmpi.so.1, libmpio.so.197 # converge-2.2.0-mpich2-04291698 # converge-2.2.0-openmpi-042916 -> libmpi.so.199 # converge-2.2.0-pmpi-042916 -> libmpi.so.1, libmpio.so.1100 # converge-2.2.0-serial-042916101 # make_surface102 # post_convert103 # 2.3.23104 # converge-2.3.23-hpmpi-linux-64 -> libmpi.so.1, libmpio.so.1105 # converge-2.3.23-mpich2-linux-64 -> libmpi.so.12106 # converge-2.3.23-openmpi-linux-64 -> libmpi.so.1107 # converge-2.3.23-pmpi-linux-64 -> libmpi.so.1, libmpio.so.1108 # converge-2.3.23-serial-linux-64109 # make_surface_64110 # post_convert_mpich_64 -> libmpi.so.12111 # post_convert_ompi_64 -> libmpi.so.1112 # post_convert_pmpi_64 -> libmpi.so.1, libmpio.so.1113 # post_convert_serial_64114 # 2.4.10115 # converge-2.4.10-intel -> libmpi.so.12, libmpifort.so.12116 # converge-2.4.10-mpich -> libmpi.so.12117 # converge-2.4.10-ompi -> libmpi.so.12118 # converge-2.4.10-pmpi -> libmpi.so.1, libmpio.so.1119 # converge-2.4.10-serial120 # make_surface_64121 # post_convert_mpich_64 -> libmpi.so.12122 # post_convert_ompi_64 -> libmpi.so.1123 # post_convert_pmpi_64 -> libmpi.so.1124 # post_convert_serial_64125 # The CONVERGE tarball comes with binaries for several MPI libraries.126 # Only install the binary that matches the MPI we are building with.127 with working_dir('l_x86_64/bin'):128 if '~mpi' in spec:129 converge = glob.glob('converge-*-serial*')130 post_convert = glob.glob('post_convert_serial*')131 elif 'hp-mpi' in spec:132 converge = glob.glob('converge-*-hpmpi*')133 # No HP-MPI version of post_convert134 post_convert = glob.glob('post_convert_serial*')135 elif 'intel-mpi' in spec or 'intel-parallel-studio+mpi' in spec:136 converge = glob.glob('converge-*-intel*')137 # No Intel MPI version of post_convert138 post_convert = glob.glob('post_convert_serial*')139 elif 'mpich' in spec:140 converge = glob.glob('converge-*-mpich*')141 post_convert = glob.glob('post_convert_mpich*')142 elif 'mvapich2' in spec:143 converge = glob.glob('converge-*-mvapich*')144 # MVAPICH2 hasn't been supported since CONVERGE145 # came with a single serial post_convert146 post_convert = glob.glob('post_convert')147 elif 'openmpi' in spec:148 converge = glob.glob('converge-*-o*mpi*')149 post_convert = glob.glob('post_convert_o*mpi*')150 elif 'platform-mpi' in spec:151 converge = glob.glob('converge-*-pmpi*')152 post_convert = glob.glob('post_convert_pmpi*')153 else:154 raise InstallError('Unsupported MPI provider')155 make_surface = glob.glob('make_surface*')156 # Old versions of CONVERGE come with a single serial post_convert157 if not post_convert:158 post_convert = glob.glob('post_convert')159 # Make sure glob actually found something160 if not converge:161 raise InstallError('converge executable not found')162 if not post_convert:163 raise InstallError('post_convert executable not found')164 if not make_surface:165 raise InstallError('make_surface executable not found')166 # Make sure glob didn't find multiple matches167 if len(converge) > 1:168 raise InstallError('multiple converge executables found')169 if len(post_convert) > 1:170 raise InstallError('multiple post_convert executables found')171 if len(make_surface) > 1:172 raise InstallError('multiple make_surface executables found')173 converge = converge[0]174 post_convert = post_convert[0]175 make_surface = make_surface[0]176 mkdir(prefix.bin)177 # Install the executables178 install(converge, join_path(prefix.bin, converge))179 install(post_convert, join_path(prefix.bin, post_convert))180 install(make_surface, join_path(prefix.bin, make_surface))181 with working_dir(prefix.bin):182 # Create generic symlinks to all executables183 if not os.path.exists('converge'):184 os.symlink(converge, 'converge')185 if not os.path.exists('post_convert'):186 os.symlink(post_convert, 'post_convert')187 if not os.path.exists('make_surface'):188 os.symlink(make_surface, 'make_surface')189 def setup_run_environment(self, env):190 # CONVERGE searches for a valid license file in:191 # $CONVERGE_ROOT/license/license.lic...

Full Screen

Full Screen

TestSimulator.py

Source:TestSimulator.py Github

copy

Full Screen

1#!/usr/bin/env python2# encoding: utf-83"""4TestSimulator.py5Created by Fredrick Stakem on 2010-05-20.6Copyright (c) 2010 __Research__. All rights reserved.7"""8# Import libraries9#------------------------------------------------------------------------------10import Simulator as s11import pdb12import numpy13import scipy14import scipy.signal15import pylab16import time17import math18from enum import Enum19from Globals import *20# Filesystem paramters21#------------------------------------------------------------------------------22dataRoot = "/Users/fstakem/Data/Movements_5_1_08/"23root = "/Users/fstakem/Research/PhD/2010_Research/SeperateConvergence/code/"24libDir = root + "lib/"25logDir = root + "log/"26outputDir = root + "output/"27# Simulation data28#------------------------------------------------------------------------------29movement = "Stacking"30simulation = 131inputFile = dataRoot + movement + "/Simulation" + str(simulation) + \32 "/positionLog.txt"33# Transmission parameters34#------------------------------------------------------------------------------35predictionInterval = 10036samplingInterval = 1037heartbeat = 50038drThreshold = 0.02539convergenceType = InterpolationType.Time40# Network parameters41#------------------------------------------------------------------------------42delay = 10043jitter = 4044packetLoss = 045# Reconstruction parameters46#------------------------------------------------------------------------------47convergenceTime = 5048longConvergenceTime = 10049# Calculation parameters50#------------------------------------------------------------------------------51jumpThreshold = 052jumpSpacing = 153# Simulate the transmission and reconstruction algorithms54#------------------------------------------------------------------------------55startTimeTotal = time.time()56transmittedData = []57simNumber = inputFile.split('/')[-2][-1]58data = s.transmitData(inputFile, logDir, predictionInterval,59 samplingInterval, heartbeat, drThreshold,60 delay, jitter, packetLoss)61snapData = s.snapReconstructData(data[5], 62 logDir, 63 simNumber, 64 samplingInterval)[0] 65convergeData = s.convergeData(data[5], logDir, simNumber, samplingInterval,66 convergenceTime)[0] 67varConvergeData = s.varConvergeData(data[5], logDir, simNumber, samplingInterval,68 convergenceTime, longConvergenceTime)[0]69data.append(snapData)70data.append(convergeData)71data.append(varConvergeData)72print "Total time spent simulating the transmission: " + str(time.time() - \73 startTimeTotal)74print75# Set the variables for the data76#------------------------------------------------------------------------------77initialData = data[1]78snapData = data[6]79convergeData = data[7]80varConvergeData = data[8]81# Calculate the results and statistics82#------------------------------------------------------------------------------83inputJump = s.calculateStats( s.findDistanceBetweenSamples(initialData,84 jumpThreshold,85 jumpSpacing) ) 86snapError = s.calculateStats( s.findDistanceError(initialData,87 snapData) )88snapJump = s.calculateStats( s.findDistanceBetweenSamples(snapData,89 jumpThreshold,90 jumpSpacing) )91convergeError = s.calculateStats( s.findDistanceError(initialData,92 convergeData) )93convergeJump = s.calculateStats( s.findDistanceBetweenSamples(convergeData,94 jumpThreshold,95 jumpSpacing) )96varConvergeError = s.calculateStats( s.findDistanceError(initialData,97 varConvergeData) )98varConvergeJump = s.calculateStats( s.findDistanceBetweenSamples(varConvergeData,99 jumpThreshold,100 jumpSpacing) )101 102# Output the statistics103#------------------------------------------------------------------------------104print "Jump:"105print "\tInput:\t\t" + str(inputJump)106print "\tSnap:\t\t" + str(snapJump)107print "\tConverge:\t" + str(convergeJump) 108print "\tVar Converge:\t" + str(varConvergeJump)109print "Error:"110print "\tSnap:\t\t" + str(snapError) 111print "\tConverge:\t" + str(convergeError)112print "\tVar Converge:\t" + str(varConvergeError)113# Seperate the singals for plotting114#------------------------------------------------------------------------------115initialTime, initialX, initialY, initialZ = s.splitData(initialData)116snapTime, snapX, snapY, snapZ = s.splitData(snapData)117convergeTime, convergeX, convergeY, convergeZ = s.splitData(convergeData)118varConvergeTime, varConvergeX, varConvergeY, varConvergeZ = s.splitData(varConvergeData)119lowerBound = 19000120upperBound = 25000121initialTime, initialX = s.cropData(initialTime, initialX, lowerBound, upperBound)122snapTime, snapX = s.cropData(snapTime, snapX, lowerBound, upperBound)123convergeTime, convergeX = s.cropData(convergeTime, convergeX, lowerBound, upperBound)124varConvergeTime, varConvergeX = s.cropData(varConvergeTime, varConvergeX, lowerBound, upperBound)125 126# Plot the signals127#------------------------------------------------------------------------------128figure = 1129pylab.figure(figure)130pylab.plot(initialTime, initialX, 'k-')131pylab.plot(snapTime, snapX, 'b-')132pylab.plot(convergeTime, convergeX, 'r-')133pylab.plot(varConvergeTime, varConvergeX, 'g-')134figure = 2135pylab.figure(figure)136pylab.plot(varConvergeTime, varConvergeX, 'g-')...

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 molecule 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