Jmeter使用指南轉(zhuǎn)_第1頁
Jmeter使用指南轉(zhuǎn)_第2頁
Jmeter使用指南轉(zhuǎn)_第3頁
Jmeter使用指南轉(zhuǎn)_第4頁
Jmeter使用指南轉(zhuǎn)_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、Jmeter使用指南 轉(zhuǎn)本文重點(diǎn)介紹JMeter工具在測試中地位以及其中一些難以理解或者手冊中含糊不清的感念,讀者可以通過本文了解這些概念,然后再根據(jù)自己的需要查閱JMeter中各個組件的具體用法來完成測試工作。1.簡介JMeter是一個專門用于測試C/S應(yīng)用的桌面測試軟件(并不適合于B/S結(jié)構(gòu),因?yàn)樗茈y模擬用戶在browser上的動作,如果需要測試B/S結(jié)構(gòu)的應(yīng)用,可以選擇Selenium這樣的工具),主要被用來完成功能測試,壓力測試,性能測試等工作。JMeter與其它測試軟件相比的優(yōu)勢如下:它可以幫助測試者很方便地模擬出多用戶同時(shí)訪問服務(wù)器的環(huán)境(通過Thread Group),這樣可以

2、檢測出很多平時(shí)在單線程環(huán)境下無法暴露出來的問題。應(yīng)用范圍很廣,幾乎所有你能想到的C/S應(yīng)用它都能夠提供了相應(yīng)的支。JMeter中自己定制了一些特定應(yīng)用的測試方案,例如對HTTP Server的測試、對數(shù)據(jù)庫的測試、對Java程序的測試等。此外即使Jmeter沒有提供當(dāng)前應(yīng)用的測試環(huán)境,用戶也可以同昨BeanShell的方式自行定制。提供了豐富的邏輯控制器,可以允許測試人員很方便地寫出一些相對復(fù)雜的測試邏輯。提供完善的變量機(jī)制以及配置機(jī)制,幫助測試人員減輕編寫用例的負(fù)擔(dān),減少重復(fù)工作。提供了強(qiáng)大的監(jiān)控組建,幫助測試人員很方便地得到測試結(jié)果統(tǒng)計(jì)信息。JMeter的劣勢:難以針對正確性進(jìn)行測試。雖然

3、JMeter提供了斷言機(jī)制,但是通常我們的測試在模擬多用戶操作,因此某個用戶發(fā)出一個請求后得到的響應(yīng)是不可預(yù)測的(例如同時(shí)對一個數(shù)據(jù)庫表進(jìn)行讀寫,雖然我們可以讓每個模擬用戶將寫入的信息存儲在某個公共區(qū)域,但仍然可能會有問題,因?yàn)閿?shù)據(jù)庫寫入的時(shí)間和寫入公共區(qū)域的時(shí)間并不能保證同步),因此如果想通過JMeter驗(yàn)證應(yīng)用的正確性還是比較麻煩的。通常我們只是利用斷言來檢查一些較為簡單而又重要的信息,例如返回碼。沒有很好的BeanShell測試機(jī)制。在JMeter中,BeanShell是非常重要的一部分,因?yàn)橥ǔMeter定制的測試方案多少與我們的應(yīng)用有些出入,這時(shí)就需要使用BeanShell來完成一

4、些JMeter無法完成的工作。然而BeanShell也是需要保證正確性的,而JMeter并沒有對BeanShell的測試提供很好的支持。通過以上的分析,可以發(fā)現(xiàn)JMeter更適合找出被測試系統(tǒng)在并發(fā)環(huán)境下存在的問題。2.JMeter測試用例的基本結(jié)構(gòu)JMeter測試用例的基本結(jié)構(gòu)是一個類似于Windows資源管理器的樹形結(jié)構(gòu),這個樹中的每一個節(jié)點(diǎn)都由一個元素來表示,因此一個完整的JMeter測試用例實(shí)際上是由一個個元素組成的,而測試的執(zhí)行過程實(shí)際上就是這些元素的執(zhí)行過程。一般而言,JMeter會使用深度優(yōu)先的方式遍歷這些元素,而對于同一層的元素,JMeter會自上至下地執(zhí)行。在JMeter中有

5、很多種元素,而每種元素在樹型結(jié)構(gòu)中都有特定的意義,為了方便理解,這里把這些元素從結(jié)構(gòu)性質(zhì)上分為三大類:第一類是控制型元素,這類元素通常出現(xiàn)在樹型結(jié)構(gòu)的枝節(jié)點(diǎn),它們被用來控制其下第一層元素(注意,不是其下所有元素)的執(zhí)行,例如控制他們的先后順序,或者執(zhí)行哪個或者不執(zhí)行哪個。通過這類元素我們就可以很方便地動態(tài)控制測試用例的執(zhí)行過程,這些元素就類似于變成語言中的if-else、switch、while等邏輯控制語句。第二類是動作型元素,這類元素是真正發(fā)起測試請求的元素,它們通常位于樹型結(jié)構(gòu)的底層,每一個動作元素代表一次請求-響應(yīng)的過程,他們的執(zhí)行順序通常被控制型元素管理。第三類是配置型元素,它們只能

6、作為樹型結(jié)構(gòu)中的葉子節(jié)點(diǎn),被用于對其作用范圍內(nèi)(作用范圍的規(guī)則如下:如果該配置元素在控制元素下,則其作用范圍為該控制元素下的所有子孫節(jié)點(diǎn);如果該配置元素在動作元素下,則其作用范圍僅為這一個動作元素)的所有動作型元素產(chǎn)生一定的影響。這些影響根據(jù)具體元素種類而不同,例如改變元素的參數(shù)、延遲請求時(shí)間、在請求前后加入一些動作、監(jiān)聽請求及其相應(yīng)。此外,如果某個動作型元素被多個相同的配置型元素影響后,這些配置型元素的效果就會進(jìn)行Merge,Merge的規(guī)則依照元素的功能類型不同而不同(詳見第3節(jié))。3.JMeter中的元素從功能上講,JMeter的元素分為八大類以及兩個特殊元素。這里從使用場合上對這些元素

7、進(jìn)行敘述,至于具體每個元素什么功能則需要查看JMeter的幫助(具體方法是點(diǎn)擊未知的元素,然后選擇Help菜單下的Help選項(xiàng))。Test Plan元素:控制型元素。只能存在于樹型結(jié)構(gòu)的根節(jié)點(diǎn)。它代表了整個測試方案,測試人員可以在這里設(shè)置一些全局性的內(nèi)容,例如全局變量(注意全局變量是Thread Local的,詳見第4節(jié))、ClassPath配置(如果希望在Jmeter中調(diào)用自己的Java類就需要在這里設(shè)置了)等。Thread Group元素:控制型元素。只能存在于Test Plan元素之下。它代表了一組行為相似的用戶,通常我們把一類用戶的動作放在同一個Thread Group下,這樣就可以模

8、擬多這這樣的用戶了。在這里可以配置模擬用戶的個數(shù)(線程的個數(shù))、循環(huán)次數(shù)、執(zhí)行時(shí)間等。Logic Controller:控制型元素??梢源嬖谟赥hread Group下任何位子。它用來完成控制其下元素的執(zhí)行,JMeter提供了很多Logic Controller類型的元素,方便我們在測試中實(shí)現(xiàn)基本的邏輯。Config Element:配置型元素。這些元素被用來改變其作用范圍內(nèi)所有動作元素的配置,利用該類元素可以減少很多測試用例編寫中的重復(fù)工作,例如可以讓一個HTTP Request Defaults元素來配置所有用例中HTTP請求的主機(jī)地址以及端口號,這樣就無須在每個動作元素中都做這樣的配置了

9、。當(dāng)Merge發(fā)生時(shí),如果某個域只有一個Config Element元素有值,則使用該值;如果某個域有多個Config Element元素有值,則使用離動作元素最近的Config Element元素的值(在動作元素節(jié)點(diǎn)下的配置元素最近)。Timer:配置型元素。如果希望控制請求發(fā)出的頻率,則應(yīng)該使用Timer延遲這些請求。當(dāng)Merge發(fā)生時(shí),所有Timer的時(shí)間會相加。Pre Processor:配置型元素。用于根據(jù)一定條件修改所有被影響的動作元素。當(dāng)Merge發(fā)生時(shí),這些Pre Processor將被依次執(zhí)行,離動作元素最遠(yuǎn)的先執(zhí)行。Post Processor:同Pre Processor

10、,只是發(fā)生在動作元素之后,用于從響應(yīng)中提取需要的信息。Assertions:配置型元素。用于對其影響范圍內(nèi)的動作元素的結(jié)果進(jìn)行斷言,例如可以斷言一些HTTP請求的返回碼,如果不通過則系統(tǒng)會記錄本次錯誤。Merge發(fā)生時(shí),所有的Assertion都會被判斷。Listener:配置型元素。用于監(jiān)聽其影響范圍內(nèi)所有動作元素,測試結(jié)果數(shù)據(jù)主要由該類元素產(chǎn)生,因此他們非常有用。Merge發(fā)生時(shí),所有的Listener監(jiān)控動作都會被執(zhí)行。Sampler:動作型元素。代表一次請求-響應(yīng)的過程,他們是測試用例中動作的發(fā)起者,是測試用例的主要元素。JMeter根據(jù)不同的應(yīng)用預(yù)制了很多種動作元素,如果用戶覺得仍然

11、不夠用甚至可以用BeanShell Sampler寫自己的動作。4.JMeter中的變量有的時(shí)候我們希望發(fā)送成千上萬個隨機(jī)的請求,或者希望本次請求的內(nèi)容依賴于前幾次的請求,那么就需要使用JMeter中的變量(注意,是Variable不是Property),這樣就可以用變量來配置每一個請求,這樣就可以讓同一個Sampler每次都能發(fā)出不同的請求。使用變量時(shí),首先必須注意的是,JMeter中的變量是線程獨(dú)立(Thread Local)的,也就是說雖然我們定義了n個變量,但是在每個線程中都有這n個變量的鏡像,他們之間相互獨(dú)立,互不干擾。當(dāng)我們希使用變量的時(shí)候,首先需要創(chuàng)建所需的變量。在JMeter中

12、創(chuàng)建變量的方式很多,一種途徑是通過Test Plan定義全局變量(用于所有的Thread Group,它也是線程獨(dú)立的),也可以通過Config Element中的User Defined Element來定義不同線程組的局部變量(注意,User Defined Element中定義的變量是用于整個線程組的,無論將這個元素放在哪里都會被應(yīng)用于整個線程組,這是一個比較特殊的配置型元素),此外當(dāng)我們在應(yīng)用中對某個沒有創(chuàng)建的變量賦值(后面會講到賦值)時(shí)也會創(chuàng)建該變量。實(shí)際上JMeter的源碼中是使用Map來實(shí)現(xiàn)變量的,因此這些性質(zhì)也不難理解。當(dāng)我們希望在某個地方引用一個變量的時(shí)候,可以通過$變量名的

13、語法來獲取變量的值。注意,如果這個變量沒有被定義,則這個式子就會被當(dāng)作普通的字符串。修改某個變量值的方法有很多,可以通過BeanShell來修改,也可以通過JMeter中一些特定的元素來修改(例如CSV Date Config Element),還可以使用JMeter函數(shù)來定義修改某個變量(具體如何做,見后面的小節(jié))。通常情況下如果我們希望在每次循環(huán)中都發(fā)出不同的請求,那么可以將可能的請求內(nèi)容放在一個文件中,并讓CSV Date Config Element從中獲取相應(yīng)的值并交給變量,也可以通過BeanShell Sampler用腳本來自己定制變量的值(注意不能使用Pre Processor中

14、的BeanShell PreProcessor來定制變量,Pre Processor是用來修改請求中的域的,這個動作發(fā)生在請求被創(chuàng)建以后。也就是說如果我們在BeanShell PreProcessor中定義了一個變量,然后寫在請求域中,那么結(jié)果就是JMeter先看到了一個沒有被賦值的變量,然后把這個$變量名式子當(dāng)作字符串處理,然后再執(zhí)行BeanShell PreProcessor。這一點(diǎn)是很多人容易犯錯誤的地方),也可以使用Pre Processor直接修改請求中的域,還可以在請求域中寫入一個JMeter函數(shù),直接生成需要的值。在有些應(yīng)用中,我們希望下一個請求的內(nèi)容依賴于之前的請求。那么我們就

15、可以通過Post Processor將響應(yīng)中的有用信息抽取出來,然后賦值給一個變量,以便下次使用。5.JMeter中的屬性在JMeter中有Property的概念,他們通常有兩種用處:首先他們代表了JMeter的配置信息(存在JMeter目錄下的bin/perties);其次他們可以被用來作為MemCache使用,以便線程間能夠通信(Properties的get和put方法是線程安全的)。Property的獲取、定義、修改一般是通過JMeter函數(shù)來完成的,當(dāng)然也可以通過強(qiáng)大的BeanShell。通常當(dāng)我們希望多個線程之間有某種依賴關(guān)系時(shí)可以使用Property,但是這樣的

16、需求并不多見,因?yàn)槲覀兡M的用戶多半都是相互獨(dú)立的,他們并不應(yīng)該知道其他人在干什么。此外我們還可以將一些常量配置在perties文件中,以便在測試中隨時(shí)使用6.JMeter中的函數(shù)有的時(shí)候我們需要執(zhí)行一些簡單的操作(例如生成一個隨機(jī)數(shù))而又不希望編寫B(tài)eanShell的Code,那么可以考慮使用JMeter中內(nèi)置的一些函數(shù)。這些函數(shù)的格式通常為$_函數(shù)名(參數(shù)1,參數(shù)2.),他們有兩種方式來返回自己的執(zhí)行結(jié)果:一種是直接返回,也就是說JMeter會在執(zhí)行該函數(shù)后用函數(shù)的返回結(jié)果來替換原來調(diào)用函數(shù)的字符串(例如假設(shè)$_method(1,2)返回world,那么如果我們在域中寫

17、hello$_method(1,2),則實(shí)際的結(jié)果是hello world)。另一種是通過參數(shù)(通常是最后一個)指定一個變量后,JMeter會將執(zhí)行結(jié)果存入該變量。具體使用哪種方式獲得結(jié)果是根據(jù)不同的函數(shù)而定的,JMeter提供了一個強(qiáng)大的函數(shù)生成器(Options菜單中的Function Helper Dialog選項(xiàng)),其中列出了所有的方法以及可能的函數(shù),并且有方便的幫助文檔,用戶可以通過該生成器來生成所需的函數(shù)。這里有必要再次強(qiáng)調(diào)JMeter讀入一個域(任何一個可以填寫內(nèi)容的空格)的過程:當(dāng)JMeter讀入一個域中的字符串后,會首先查看其中的是否存在能夠匹配$.的字符串,如果有則遞歸地解

18、析這個$.中的字符串,直到括號中的字符串不再包含括號為止。然后再解析這個$.是否為一個函數(shù)或變量,如果是則用其結(jié)果覆蓋原來的$.字符串,直至將整個字符串解析完畢。例如在輸入欄中輸入hello$_method($num,2),而num變量的值為1,則這個字符串首先被轉(zhuǎn)化為hello$_method(1,2),然后由于$_method(1,2)的值為world,則最終這個域中的內(nèi)容為hello world。掌握了以上內(nèi)容后基本就可以將JMeter中的函數(shù)和變量運(yùn)用自入了,而讀者所需做得事情只是查看手冊了解那些函數(shù)能夠提供何種功能。(注意有些函數(shù)是不能放入一些特殊的域中的,例如$_threadNum

19、就不能放在Test Plan的變量定義或者User Defined Element中的變量定義域中,具體原因手冊上講的很明白)7.JMeter中的BeanShell在多數(shù)情況下,JMeter提供的功能是不夠我們使用的,我們的測試用例中可能會存在一些比較復(fù)雜的邏輯,而這些邏輯又不發(fā)通過簡單的函數(shù)來實(shí)現(xiàn),那么我們就必須動用強(qiáng)大的BeanShell了(JMeter有一些元素專門用于在測試的不同地方加入BeanShell腳本,如BeanShell Sampler)。不幸的是,JMeter的手冊中并沒有介紹BeanShell如何使用,而是把責(zé)任全部推給了BeanShell的網(wǎng)站,BeanShell的網(wǎng)站

20、中的確有完整的BeanShell使用手冊,但是我們總不希望為了做測試又去學(xué)習(xí)一個腳本語言,因此這里給出了一些BeanShell的簡單應(yīng)用,如果覺得不夠的話再去查看更加復(fù)雜的應(yīng)用。7.1 BeanShell快速上手BeanShell是面向Java的腳本語言,因此如果你想在完全不會BeanShell的前提下使用他,那么直接編寫Java code就可以了。唯一需要注意的是,BeanShell支持若類型的變量,也就是不用指定變量類型,只要給他賦值就好了,BeanShell知道這個變量的類型。無論這個若類型變量在哪里被使用,其后的代碼都能訪問這個變量,這與強(qiáng)類型俄變量不同。例如:view plainco

21、py to clipboardprint?/Arbitrary code blocky=2;/Untyped variable assigned int x=1;/Typed variable assignedprint(y);/2 print(x);/Error!x is undefined./Arbitrary code blocky=2;/Untyped variable assigned int x=1;/Typed variable assignedprint(y);/2 print(x);/Error!x is undefined.7.2 JMeter內(nèi)置變量JMeter在它的Be

22、anShell中內(nèi)置了變量,用戶可以通過這些變量與JMeter進(jìn)行交互,其中主要的變量及其使用方法如下(JMeter文檔并沒有對該部分內(nèi)容進(jìn)行詳細(xì)講解,這里也會說明他們分別對應(yīng)于JavaDoc中的哪個類):vars:這個變量實(shí)際引用了JMeter線程中的局部變量容器(本質(zhì)上是Map),因此可以通過put和get方法訪問JMeter中的變量。這個變量是所有內(nèi)置變量中最有用的,它是測試用例與BeanShell交互的橋梁。對應(yīng)于org.apache.jmeter.threads.JMeterVariablesprops:該變量引用了JMeter的配置信息,它的使用方法與vars類似,但是只能put進(jìn)

23、去String類型的值,而不能是一個對象。對應(yīng)于java.util.Properties。ctx:該變量引用了當(dāng)前線程的上下文,理論上通過這個東西我們幾乎可以控制當(dāng)前線程相關(guān)的一切,不過這要求使用者非常熟悉JMeter的源碼。對應(yīng)于org.apache.jmeter.threads.JMeterContext。7.3在BeanShell中使用Java類有的時(shí)候我們希望發(fā)送數(shù)個請求,而這些請求的內(nèi)容是通過一個Java類來實(shí)現(xiàn)的,這時(shí)就需要讓JMeter來調(diào)用這個Java類,而唯一的途徑就是通過BeanShell。為了能夠加載Java類,我們首先需要在Test Plan中添加自定義Java類所在的

24、Class Path,然后就可以在BeanShell中import這個Java類,最后再將獲得的內(nèi)容放入vars變量中,這樣就可以在其他地方通過$.的方式獲取該變量的信息了。例如,創(chuàng)建了一個com.linhao.A類在/root/Java文件夾下,該類有一個方法hello()返回一個Hello World字符串,那么如果想在請求中使用這個方法返回的字符串,則進(jìn)行如下操作:首先在Test Plan下添加ClassPath為/root/Java然后在請求前添加一個BeanShell Sampler并寫入如下代碼:view plaincopy to clipboardprint?import com

25、.linhao.A;vars.put(word,A.hello();import com.linhao.A;vars.put(word,A.hello();最后在需要使用該字符串的地方寫$word,這樣最終這個域?qū)⒈惶鎿Q為Hello World 7.4 JMeter下BeanShell的調(diào)試BeanShell也是代碼,應(yīng)此也可能會有錯誤,而JMeter又是一個圖形界面的程序(也有命令行模式,但并不變于在設(shè)計(jì)用例階段使用),因此很多時(shí)候用例的設(shè)計(jì)者并不能確定BeanShell中某些變量是否正確。一個簡單的辦法是使用BeanShell創(chuàng)建一個對話框,然后將需要檢測的變量值顯示在對話框中。代碼如下:

26、view plaincopy to clipboardprint?JFrame.frame.=new JFrame(a);/a is avariable to be checked frame.setVisible(true);JFrame.frame.=new JFrame(a);/a is avariable to be checked frame.setVisible(true);這樣當(dāng)測試執(zhí)行到這里的時(shí)候就可以知道變量a的值了。雖然BeanShell很強(qiáng)大,但是它畢竟是一個腳本語言,因此如果測試參數(shù)的生成邏輯很復(fù)雜,則還是應(yīng)該把主要邏輯放在Java類中,然后讓BeanShell去調(diào)用,

27、BeanShell只用來處理一些較為簡單的操作8、Jmeter使用之常用函數(shù)介紹_Random函數(shù)功能:這個函數(shù)是從某個數(shù)字段隨機(jī)讀取數(shù)據(jù)替換參數(shù),可以利用在測試需要添加多條數(shù)據(jù)記錄而且某些字段需要唯一性的測試腳本中,隨機(jī)生成的參數(shù)是數(shù)字作用:可以用來實(shí)現(xiàn)參數(shù)化http請求發(fā)送的參數(shù),使得在Jmeter運(yùn)行時(shí)參數(shù)化了的參數(shù)在每個線程去不同的隨機(jī)數(shù)。如果某個參數(shù)每次發(fā)送請求的時(shí)候不能重復(fù)才可以存儲到數(shù)據(jù)庫中,則用這個功能十分方便。使用:1.點(diǎn)擊Jmeter的選項(xiàng),選擇函數(shù)助手對話框(或者使用快捷鍵Ctrl+F),在選擇一個功能的下拉框中選擇_Random。2.配置_Random函數(shù),第一個參數(shù)是

28、一個范圍內(nèi)的最小值,即所要取的隨機(jī)數(shù)的最小值,我們設(shè)置成1;第二個參數(shù)是一個范圍內(nèi)的最大值,即所要取的隨機(jī)數(shù)的最大值,我們設(shè)置成100;第三個參數(shù)是函數(shù)名稱,即用于存儲在測試計(jì)劃中其他的方式使用的值,我們設(shè)置成Random。設(shè)置好上面的三個參數(shù)后,點(diǎn)擊生成按鈕,這樣就會在對話框的最下面生成一個字符串$_Random(1,100,Random),在我們編寫的腳本中,找到要替換的參數(shù),把它的值換成前面生成的字符串就可以了,然后每次運(yùn)行的時(shí)候,這個參數(shù)會變成一個1到100之間的隨機(jī)數(shù)。_counter函數(shù)功能:這個函數(shù)是一個計(jì)數(shù)器,用于統(tǒng)計(jì)函數(shù)的使用次數(shù),它從1開始,每調(diào)用這個函數(shù)一次它就會自動加1,它有兩個參數(shù),第一個參數(shù)是布爾型的,只能設(shè)置成TRUE或者FALSE,如果是TRUE,那么每個用戶有自己的計(jì)數(shù)器,可以用于統(tǒng)計(jì)每個線程歌執(zhí)行了多少次。如果是FALSE,那就使用全局計(jì)數(shù)器,可以統(tǒng)計(jì)出這次測試共運(yùn)行了多少次。第二個參數(shù)是函數(shù)名稱格式:$_counter(FALSE,test)使用:我

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論