亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

文章標(biāo)題

2019-11-10 20:23:39
字體:
供稿:網(wǎng)友

先介紹下這篇博文的由來,之前已經(jīng)對(duì)JUnit的使用經(jīng)行了深入的介紹和演示(參考JUnit學(xué)習(xí)(一),JUnit學(xué)習(xí)(二)),其中的部分功能是通過分析JUnit源代碼找到的。得益于這個(gè)過程有幸完整的拜讀了JUnit的源碼十分贊嘆作者代碼的精美,一直計(jì)劃著把源碼的分析也寫出來。突發(fā)奇想決定從設(shè)計(jì)模式入手賞析JUnit的流程和模式的應(yīng)用,希望由此能寫出一篇耐讀好看的文章。于是又花了些時(shí)日重讀《設(shè)計(jì)模式》以期能夠順暢的把兩者結(jié)合在一起,由于個(gè)人水平有限難免出現(xiàn)錯(cuò)誤、疏漏,還請(qǐng)各位高手多多指出、討論。

測(cè)試用例的一生——運(yùn)行流程圖

這里寫圖片描述

圖一 TestCase運(yùn)行時(shí)序圖

首先,介紹下JUnit的測(cè)試用例運(yùn)行會(huì)經(jīng)過哪些過程,這里說起來有些抽象會(huì)讓人比較迷惑,在看了后面章節(jié)的內(nèi)容之后就比較清晰了:

Client(JUnitCore、Eclipse):這里是TestCase開始的地方,如果是Main函數(shù)來啟動(dòng)測(cè)試用例的話一般會(huì)調(diào)用JUnitCore的方法,如果是在Eclipse中使用JUnit插件則實(shí)際上調(diào)用的是org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference這個(gè)類。 Request(org.junit.runner.Request):Client會(huì)根據(jù)測(cè)試類或方法而創(chuàng)建一個(gè)Request實(shí)體,Request包含了要被執(zhí)行的測(cè)試類、測(cè)試方法等信息。 RunnerBuilder:在創(chuàng)建后Client調(diào)用Request.getRunner()方法獲取用于執(zhí)行測(cè)試的Runner,該過程是由RunnerBuilder這個(gè)工廠類完成的。 RunNotifier:在執(zhí)行Runner.run方法時(shí)Client還會(huì)傳遞一個(gè)RunNotifier對(duì)象,是事件的監(jiān)聽器的管理員。Runner在開始執(zhí)行、成功、失敗和執(zhí)行結(jié)束時(shí)會(huì)調(diào)用RunNotifier中相應(yīng)的方法從而發(fā)送事件給注冊(cè)了的監(jiān)聽器,JUnit運(yùn)行的最終結(jié)果就是這些監(jiān)聽器收集展現(xiàn)的。 Runner:從名字可以猜出這里應(yīng)該是測(cè)試用例運(yùn)行的地方了,在Client調(diào)用了Runner.run()方法之后,Runner會(huì)先構(gòu)造Statement對(duì)象將所有要執(zhí)行的邏輯委托給它,接著執(zhí)行Statement.evaluate()方法。在這期間Runner會(huì)觸發(fā)RunNotifier(如測(cè)試開始、測(cè)試結(jié)束等等)。 Statement:測(cè)試用例的運(yùn)行時(shí)描述,關(guān)注于測(cè)試用例如何運(yùn)行和調(diào)用測(cè)試代碼。比如在執(zhí)行測(cè)試用例前是否有@Before注釋的方法需要調(diào)用等信息都會(huì)被Runner構(gòu)造為Statement。

JUnit的類設(shè)計(jì)和模式應(yīng)用

這里寫圖片描述

圖二 JUnit的類結(jié)構(gòu)

首先先介紹下JUnit中的模型類(Model),在JUnit模型類可以劃分為三個(gè)范圍:

描述模型:是對(duì)要執(zhí)行的測(cè)試用例的描述(比如要執(zhí)行哪個(gè)類的哪個(gè)方法,是否有指定Runner,使用了哪些注解等),這一層類似于流程文件之于流程引擎——不是用來執(zhí)行的,而是描述要有哪些環(huán)節(jié)、細(xì)節(jié)。個(gè)人認(rèn)為這一模型包括測(cè)試類本身(即你自己編寫的測(cè)試用例)和Request。其中測(cè)試類本身等同于描述文件,Request則記錄了是要運(yùn)行的Suit、測(cè)試類或者是某個(gè)具體的方法、過濾器、排序的Comparator等信息(JUnit是支持對(duì)測(cè)試方法排序和過濾的)。運(yùn)行時(shí)模型:是JUnit中可執(zhí)行的模型,包括FrameworkMember(org.junit.runners.model.FrameworkMember)及其子類、TestClass(org.junit.runners.model.TestClass)、Statement。FrameworkMember的子類包括FrameworkMethod和FrameworkField分別描述了測(cè)試類的方法和變量信息,比如是否為靜態(tài)、作用域、包含哪些注解等JUnit運(yùn)行時(shí)需要用到的信息;TestClass的作用有些類似FrameworkMember,是針對(duì)測(cè)試的Class的描述。Statement在上面已經(jīng)介紹過是對(duì)測(cè)試執(zhí)行流程和細(xì)節(jié)的描述。

結(jié)果模型:JUnit中用于描述用例的類,包括Description(org.junit.runner.Description)、Result(org.junit.runner.Result)、Failure(org.junit.runner.notification.Failure)。Description是對(duì)測(cè)試用例的描述(測(cè)試名稱、所在Class的名字、是否是suit等等)只為RunNotifier提供服務(wù)。Result是運(yùn)行結(jié)果的描述,用例執(zhí)行完成后RunNotifier的 fireTestRunFinished(final Result result)方法會(huì)被觸發(fā),傳入的Result實(shí)例描述了運(yùn)行耗時(shí)、忽略的用例次數(shù)、是否成功等信息。Failure則是用例失敗后Runner傳遞給RunNotifier的對(duì)象用于描述錯(cuò)誤信息,特別包含了錯(cuò)誤的StackTrace。 言歸正傳,下面討論設(shè)計(jì)模式和JUnit的源碼:

工廠方法模式、職責(zé)鏈:用例啟動(dòng),Client在創(chuàng)建Request后會(huì)調(diào)用RunnerBuilder(工廠方法的抽象類)來創(chuàng)建Runner,默認(rèn)的實(shí)現(xiàn)是AllDefaultPosibilitiesBuilder,根據(jù)不同的測(cè)試類定義(@RunWith的信息)返回Runner。AllDefaultPosibilitiesBuilder使用職責(zé)鏈模式來創(chuàng)建Runner,部分代碼如下。代碼A是AllDefaultPosibilitiesBuilder的主要構(gòu)造邏輯構(gòu)造了一個(gè)【IgnoreBuilder->AnnotatedBuilder->SuitMethodBuilder->JUnit3Builder->JUnit4Builder】的職責(zé)鏈,構(gòu)造Runner的過程中有且只有一個(gè)handler會(huì)響應(yīng)請(qǐng)求。代碼B是Junit4Builder類實(shí)現(xiàn)會(huì)返回一個(gè)BlockJUnit4ClassRunner對(duì)象,這個(gè)是JUnit4的默認(rèn)Runner。public Runner runnerForClass(Class<?> testClass) throws Throwable { List<RunnerBuilder> builders = Arrays.asList( ignoredBuilder(), annotatedBuilder(), suiteMethodBuilder(), junit3Builder(), junit4Builder()); for (RunnerBuilder each : builders) { Runner runner = each.safeRunnerForClass(testClass); if (runner != null) { return runner; } } return null; }

代碼A 職責(zé)鏈實(shí)現(xiàn)

public class JUnit4Builder extends RunnerBuilder { @Override public Runner runnerForClass(Class<?> testClass) throws Throwable { return new BlockJUnit4ClassRunner(testClass); }}

代碼B JUnit4Builder實(shí)現(xiàn)

組合模式:將具備樹形結(jié)構(gòu)的數(shù)據(jù)抽象出公共的接口,在遍歷的過程中應(yīng)用同樣的處理方式。這個(gè)模式在Runner中的應(yīng)用不是很明顯,扣進(jìn)來略有牽強(qiáng)。Runner是分層次的,父層包括@BeforeClass、@AfterClass、@ClassRule注解修飾的方法或變量,它們?cè)跍y(cè)試執(zhí)行前或執(zhí)行后執(zhí)行一次。兒子層是@Before、@After、@Rule修飾的方法或變量它們?cè)诿總€(gè)測(cè)試方法執(zhí)行前后執(zhí)行。當(dāng)編寫的用例使用Suit來運(yùn)行時(shí)則是三層結(jié)構(gòu),上面的父子結(jié)構(gòu)中間插入了一層childrenRunners,也就是一個(gè)Suilt中每個(gè)測(cè)試類都會(huì)生成一個(gè)Runner,調(diào)用順序變成了Runner.run()>childRunner.run()<即遍歷childrenRunners>->testMethod()。ParentRunner中將變化的部分封裝為runChild()方法交給子類實(shí)現(xiàn),達(dá)到了遍歷過程使用同樣處理方式的目的——ParentRunner.this.runChild(each,notifier)。public void run(final RunNotifier notifier) { EachTestNotifier testNotifier = new EachTestNotifier(notifier, getDescription()); try { Statement statement = classBlock(notifier); statement.evaluate(); } catch (AssumptionViolatedException e) { testNotifier.fireTestIgnored(); } catch (StoppedByUserException e) { throw e; } catch (Throwable e) { testNotifier.addFailure(e); } } PRivate void runChildren(final RunNotifier notifier) { for (final T each : getFilteredChildren()) { fScheduler.schedule(new Runnable() { public void run() { ParentRunner.this.runChild(each, notifier); } }); } fScheduler.finished(); }

代碼C ParentRunner的組合模式應(yīng)用

模板方法模式:模板方法的目的是抽取公共部分封裝變化,在父類中會(huì)包含公共流程的代碼,將變化的部分封裝為抽象方法由子類實(shí)現(xiàn)(就像模板一樣框架式定好的,你去填寫你需要的內(nèi)容就行了)。JUnit的默認(rèn)Runner——BlockJUnit4ClassRunner繼承自ParentRunner,ParentRunner類定義了Statement的構(gòu)造和執(zhí)行流程,而如何執(zhí)行兒子層的runChild方法時(shí)交給子類實(shí)現(xiàn)的,在BlockJUnit4ClassRunner中就是去構(gòu)造和運(yùn)行TestMethod,而另一個(gè)子類Suit中則是執(zhí)行子層次的runner.run。

這里寫圖片描述 圖三 RunNotifier的公共方法

private abstract class SafeNotifier { private final List<RunListener> fCurrentListeners; SafeNotifier() { this(fListeners); } SafeNotifier(List<RunListener> currentListeners) { fCurrentListeners = currentListeners; } void run() { synchronized (fListeners) { List<RunListener> safeListeners = new ArrayList<RunListener>(); List<Failure> failures = new ArrayList<Failure>(); for (Iterator<RunListener> all = fCurrentListeners.iterator(); all .hasNext(); ) { try { RunListener listener = all.next(); notifyListener(listener); safeListeners.add(listener); } catch (Exception e) { failures.add(new Failure(Description.TEST_MECHANISM, e)); } } fireTestFailures(safeListeners, failures); } } abstract protected void notifyListener(RunListener each) throws Exception; }public void fireTestRunStarted(final Description description) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testRunStarted(description); } ; }.run(); }

代碼D RunNotifier代碼截取

裝飾模式:保持對(duì)象原有的接口不改變而透明的增加對(duì)象的行為,看起來像是在原有對(duì)象外面包裝了一層(或多層)行為——雖然對(duì)象還是原來的類型但是行為逐漸豐富起來。 之前一直在強(qiáng)調(diào)Statement描述了測(cè)試類的執(zhí)行細(xì)節(jié),到底是如何描述的呢?代碼E展示了Statement的構(gòu)筑過程,首先是調(diào)用childrenInvoker方法構(gòu)建了Statement的基本行為——執(zhí)行所有的子測(cè)試runChildren(notifier)(非Suit情況下就是TestMethod了,如果是Suit的話則是childrenRunners)。接著是裝飾模式的應(yīng)用,代碼F是withBeforeClasses()的實(shí)現(xiàn)——很簡(jiǎn)單,檢查是否使用了@BeforeClasses注解修飾如果存在構(gòu)造RunBefores對(duì)象——RunBefore繼承自Statement。代碼H中的evaluate()方法可以發(fā)現(xiàn)新生成的Statement在執(zhí)行runChildren(fNext.evaluate())之前遍歷所有使用@BeforeClasses注解修飾的方法并執(zhí)行。產(chǎn)生的效果即使用@BeforeClasses修飾的方法會(huì)在所有用例運(yùn)行前執(zhí)行且只執(zhí)行一次。后面的withAfterClasses、withClassRules方法原理一樣都使用了裝飾模式,不再贅述。protected Statement classBlock(final RunNotifier notifier) { Statement statement = childrenInvoker(notifier); statement = withBeforeClasses(statement); statement = withAfterClasses(statement); statement = withClassRules(statement); return statement; } protected Statement childrenInvoker(final RunNotifier notifier) { return new Statement() { @Override public void evaluate() { runChildren(notifier); } }; }

代碼E Statement的構(gòu)造

protected Statement withBeforeClasses(Statement statement) { List<FrameworkMethod> befores = fTestClass .getAnnotatedMethods(BeforeClass.class); return befores.isEmpty() ? statement : new RunBefores(statement, befores, null); }

代碼F withBeforeClasses實(shí)現(xiàn)

public class RunBefores extends Statement { private final Statement fNext; private final Object fTarget; private final List<FrameworkMethod> fBefores; public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) { fNext = next; fBefores = befores; fTarget = target; } @Override public void evaluate() throws Throwable { for (FrameworkMethod before : fBefores) { before.invokeExplosively(fTarget); } fNext.evaluate(); }}

代碼H RunBefores實(shí)現(xiàn)

策略模式:針對(duì)相同的行為在不同場(chǎng)景下算法不同的情況,抽象出接口類,在子類中實(shí)現(xiàn)不同的算法并提供算法執(zhí)行必須Context信息。JUnit中提供了Timeout、ExpectedException、ExternalResource等一系列的TestRule用于豐富測(cè)試用例的行為,這些TestRule的都是通過修飾Statement實(shí)現(xiàn)的。修飾Statement的代碼在withRules()方法中實(shí)現(xiàn),使用了策略模式。代碼I描述了JUnit是如何處理@Rule標(biāo)簽的,withRules方法獲取到測(cè)試類中所有的@Rule修飾的變量,分別調(diào)用withMethodRules和withTestRules方法,前者是為了兼容JUnit3版本的Rule這里忽略,后者withTestRules的邏輯很簡(jiǎn)單首先查看是否使用了@Rule,如存在就交給RunRules類處理。代碼J是RunRules的實(shí)現(xiàn),在構(gòu)造函數(shù)中處理了修飾Statement的邏輯(applyAll方法)——抽象接口是TestRule,根據(jù)不同的場(chǎng)景(即使用@Rule修飾的不同的TestRule的實(shí)現(xiàn))選擇不同的策略(TestRule的具體實(shí)現(xiàn)),而Context信息就是入?yún)ⅲ╮esult:Statement, description:Description)。private Statement withRules(FrameworkMethod method, Object target, Statement statement) { List<TestRule> testRules = getTestRules(target); Statement result = statement; result = withMethodRules(method, testRules, target, result); result = withTestRules(method, testRules, result); return result; }private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules, Statement statement) { return testRules.isEmpty() ? statement : new RunRules(statement, testRules, describeChild(method)); }

代碼I rule的執(zhí)行

public class RunRules extends Statement { private final Statement statement; public RunRules(Statement base, Iterable<TestRule> rules, Description description) { statement = applyAll(base, rules, description); } @Override public void evaluate() throws Throwable { statement.evaluate(); } private static Statement applyAll(Statement result, Iterable<TestRule> rules, Description description) { for (TestRule each : rules) { result = each.apply(result, description); } return result; }}

代碼J RunRules實(shí)現(xiàn)

這里簡(jiǎn)單舉一個(gè)Timeout的代碼。Timeout首先實(shí)現(xiàn)了TestRule方法并在apply中定義了自己的算法——構(gòu)造一個(gè)FailOnTimeout對(duì)象并返回。不再詳細(xì)描述FailOnTimeout的實(shí)現(xiàn),主要原理就是起一個(gè)線程來跑測(cè)試代碼并等待線程指定的時(shí)間,如果超時(shí)就會(huì)拋出異常。public class Timeout implements TestRule { private final int fMillis; /** * @param millis the millisecond timeout */ public Timeout(int millis) { fMillis = millis; } public Statement apply(Statement base, Description description) { return new FailOnTimeout(base, fMillis); }}

代碼K Timeout實(shí)現(xiàn)

外觀模式:封裝統(tǒng)一的對(duì)外接口,隱藏內(nèi)部各個(gè)小模塊之間的調(diào)用細(xì)節(jié),使得用戶既可以簡(jiǎn)單的使用facade來達(dá)到目的,必要時(shí)又可以自行操作內(nèi)部對(duì)象。這里的舉例可能不是非常明顯。圖四是TestClass的公共方法,代碼L給出了 TestClass(org.junit.runners.model.TestClass)的一小部分代碼,TestClass主要作用是封裝對(duì)Class的操作提供了JUnit運(yùn)行時(shí)需要用到的功能并隱藏其中操作的細(xì)節(jié)。在TestClass內(nèi)部將功能委托給了三個(gè)對(duì)象Class(java.lang.Class)、FrameworkMethod、FrameworkField來實(shí)現(xiàn),本身充當(dāng)了外觀(facade)對(duì)外提供了getName、getOnlyConstructor、getAnnotations等等接口,在必要的時(shí)又可以通過這個(gè)外觀獲取到Class、FrameworkMethod等對(duì)象。

這里寫圖片描述

圖四 TestClass的公共方法

public class TestClass { private final Class<?> fClass; private Map<Class<?>, List<FrameworkMethod>> fMethodsForAnnotations = new HashMap<Class<?>, List<FrameworkMethod>>(); private Map<Class<?>, List<FrameworkField>> fFieldsForAnnotations = new HashMap<Class<?>, List<FrameworkField>>(); /** * Creates a {@code TestClass} wrapping {@code klass}. Each time this * constructor executes, the class is scanned for annotations, which can be * an expensive process (we hope in future JDK's it will not be.) Therefore, * try to share instances of {@code TestClass} where possible. */ public TestClass(Class<?> klass) { fClass = klass; if (klass != null && klass.getConstructors().length > 1) { throw new IllegalArgumentException( "Test class can only have one constructor"); } for (Class<?> eachClass : getSuperClasses(fClass)) { for (Method eachMethod : MethodSorter.getDeclaredMethods(eachClass)) { addToAnnotationLists(new FrameworkMethod(eachMethod), fMethodsForAnnotations); } for (Field eachField : eachClass.getDeclaredFields()) { addToAnnotationLists(new FrameworkField(eachField), fFieldsForAnnotations); } } } ……}

代碼L TestClass截取

寫在最后

讀JUnit代碼時(shí)確實(shí)非常贊嘆其合理的封裝和靈活的設(shè)計(jì),自己雖然也寫了幾年代碼但是在JUnit的源碼中收獲很多。由于對(duì)源碼的鉆研深度以及設(shè)計(jì)模式的領(lǐng)會(huì)不夠深入,文中有很多牽強(qiáng)和錯(cuò)誤的地方歡迎大家討論指正。最喜歡的是JUnit對(duì)裝飾模式和職責(zé)鏈的應(yīng)用,在看到AllDefaultPossiblitiesBuilder中對(duì)職責(zé)鏈的應(yīng)用還覺得設(shè)計(jì)比較合理,等到看到Statement的創(chuàng)建和組裝就感慨設(shè)計(jì)的精湛了,無論是基本的調(diào)用測(cè)試方法的邏輯還是@Before、@After等以及實(shí)現(xiàn)自TestRule的邏輯一并融入到Statement的構(gòu)造中,又不會(huì)牽扯出太多的耦合。總之無論是設(shè)計(jì)模式還是設(shè)計(jì)思想,歸根結(jié)底就是抽取公共部分,封裝變化,做到靈活、解耦。最后說明這篇文章根據(jù)的源代碼是JUnit4.11的,maven坐標(biāo)如下,在JUnit的其它版本中源碼差別比較大沒有研究過。<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency>

轉(zhuǎn)自:junit源碼與設(shè)計(jì)模式欣賞


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产黄色录像片| 日本精品www| 天海翼一区二区三区四区在线观看| 自拍视频一区| 7777精品伊人久久久大香线蕉经典版下载| 国产在线一区不卡| 日本激情视频在线| 亚洲综合在线网| 日韩中文一区| 国产精品欧美久久久| 亚洲精品乱码久久久久久蜜桃麻豆| 精品视频高清无人区区二区三区| 久久福利视频网| 亚洲国产欧美一区二区三区不卡| 国产精品18久久久久久首页狼| 四虎永久免费影院| 传媒av在线| 3d动漫成人在线| 成人在线看片网站| 国产h色视频在线观看| 久久久久国产精品一区三寸| 91精品国产欧美一区二区18| 天堂av资源网| 欧美日韩高清在线| 午夜av一区二区三区| 国产欧美一区二区精品秋霞影院| 自拍偷拍亚洲区| 日韩8x8x| 亚洲 高清 成人 动漫| 嫩呦国产一区二区三区av| 亚洲在线免费观看视频| 肉色丝袜一区二区| 国产成人亚洲综合91精品| 中文字幕第一页在线视频| 久久久久香蕉视频| 丰满岳妇乱一区二区三区| 综合国产精品久久久| 台湾佬中文娱乐网欧美电影| 欧美顶级xxxxbbbb| 超碰超碰超碰超碰超碰| 激情亚洲网站| 欧美一级特黄高清视频| 99精品老司机免费视频| 中文字幕色婷婷在线视频| 米仓穗香在线观看| 亚洲国产欧美日本视频| 欧美精品在欧美一区二区| 午夜视频久久久| 亚洲成人午夜电影| 亚洲女人小视频在线观看| 午夜激情一区二区三区| 欧美国产1区2区| 日韩精彩视频在线观看| 久久精品老司机| 97视频在线观看网站| 4444kk亚洲人成电影在线| 国产农村妇女毛片精品| 日韩精品一区二区三区swag| 亚洲蜜桃视频| 亚洲啪av永久无码精品放毛片| 日本精品久久久久久| 国产女人高潮时对白| 国产精品一区二区你懂的| 亚洲欧美中文字幕| 黄动漫在线看| 一本一本久久a久久| 在线免费av资源| 激情国产一区二区| 国产成人精品一区二区三区福利| 亚洲精品视频一区| 久久久久久久国产精品| 日韩av自拍偷拍| 美女100%无挡| 日韩av电影国产| 99久久久无码国产精品性| 日韩电影免费观看高清完整版在线观看| 日韩日韩日韩日韩| 婷婷激情久久| 开心婷婷激情| 99视频在线免费播放| 国产精品日韩精品在线播放| 漫画在线观看av| 国产成a人无v码亚洲福利| 在线观看成人免费| 日韩高清一级片| 97久久久精品综合88久久| 蜜桃av久久久亚洲精品| 男男一级淫片免费播放| 国产精品入口福利| 国产免费嫩草影院| 在线观看av网站永久| 亚洲欧美日韩久久| 国产尤物精品| 欧美视频一区二区在线| 米奇777在线欧美播放| 91嫩草香蕉| 日本成人精品视频| 波多野结衣激情| 日韩毛片精品高清免费| 久久9999久久免费精品国产| 日韩毛片在线看| 九九热r在线视频精品| 亚洲精品第三页| 日韩a一级欧美一级| 色婷婷狠狠五月综合天色拍| 九色视频在线播放| www.久久久久久久久| 91久久国产综合久久91| 午夜精品福利视频网站| 日韩精品视频一区二区| 日本网站在线观看一区二区三区| 亚洲男人的天堂在线观看| 日本泡妞xxxx免费视频软件| 国产精品自产拍在线网站| 成人国产综合| 99热免费在线| 国产日本欧美一区二区三区在线| 国内精品伊人久久久久影院对白| 香港三日本三级少妇66| 天天综合日日夜夜精品| 蜜乳av另类精品一区二区| 午夜视频福利在线观看| 亚洲精品中文字幕有码专区| 精品9999| 国产 日韩 欧美 精品| 97se亚洲国产综合自在线| 伊人久久大香线蕉精品| 高清精品久久| 日韩精品久久久久久久的张开腿让| 激情视频亚洲| 国产精品v片在线观看不卡| 亚洲经典三级| 中文字幕高清在线免费播放| 亚洲有码转帖| 妞干网在线免费视频| 亚洲人成电影在线| 69看片网站| 精品一区二区三区免费毛片爱| 日韩在线观看免费高清完整版| 校园春色亚洲| 在线日韩日本国产亚洲| 中文视频一区视频二区视频三区| 久久96国产精品久久99软件| 91精品国产综合久久香蕉922| 欧美日韩精品久久| 日韩一级片在线观看| 日韩乱码人妻无码中文字幕久久| 亚洲综合偷拍欧美一区色| 国产成人黄色片| 日日噜噜夜夜狠狠久久波多野| 老司机av福利| 丝袜美腿玉足3d专区一区| 捆绑紧缚一区二区三区在线观看| 最近中文字幕mv免费高清电影| 欧美国产日本韩| 69sex久久精品国产麻豆| 9.1国产丝袜在线观看| 亚洲观看高清完整版在线观看| 国产美女主播视频一区| 中文字幕日韩第一页| 男女激情视频一区| 黄色正能量网站| 日韩高清在线不卡| 黄网免费视频| 日韩成人精品视频在线观看| 欧美日韩成人网| 欧美aaaaa性bbbbb小妇| 97人人做人人爱| 成人毛片在线播放| 色婷婷综合缴情免费观看| 制服.丝袜.亚洲.中文.综合| 亚洲另类色综合网站| 操人视频欧美| 国产精品久久久久7777| 色综合久久久久综合一本到桃花网| 亚洲色图20p| 欧洲亚洲在线视频| 午夜在线a亚洲v天堂网2018| 91性感美女视频| 婷婷激情综合| 草民电影神马电影一区二区| 黄色网页在线| 日本韩国欧美超级黄在线观看| 鲁丝一区二区三区| 欧美黄色一区二区三区| 亚洲夜晚福利在线观看| 欧美一区二区视频在线观看2020| 欧美xxx另类| 182在线视频观看| 尤物99国产成人精品视频| 白白色在线观看| 日韩在线免费视频观看| 天天操天天插天天射| 欧美中文高清| 亚洲第一精品在线| 中文有码一区| 成年人网站在线观看免费| 菠萝菠萝蜜在线观看| 最新在线你懂的| 麻豆精品国产传媒mv男同| 久久综合狠狠综合久久激情| 亚洲欧美日韩一区在线| 黄色动漫在线免费看| 欧美黑人xxxxx| 成人18在线| 亚洲一区 欧美| 久久99国产精品免费网站| 一本色道久久综合狠狠躁篇的优点| 日韩欧美高清在线视频| 99在线观看免费视频精品观看| 亚洲精品手机在线观看| 日韩欧美在线一区二区| 欧美日韩成人精品| 国产日韩av在线| 91国偷自产一区二区开放时间| 日韩综合一区二区| 一级黄色电影片| 在线观看成人毛片| 成人免费视频播放| 色一情一交一乱一区二区三区| 韩国三级hd两男一女| 久久久综合av| 噜噜噜久久,亚洲精品国产品| 丰满少妇久久久| 少妇视频一区二区| 一区二区三区视频在线观看视频| 美国黄色一级视频| 偷偷色噜狠狠狠狠的777米奇| 天天综合91| 日韩少妇内射免费播放| 午夜激情在线视频| 1024手机看片国产| 欧美激情三级免费| 欧美一级高清免费播放| 亚洲ab电影| 老师我好爽再深一点的视频| 狠狠色噜噜狠狠狠狠888奇米| eeuss影院eeuss最新直达| 国产毛片毛片毛片| 先锋资源久久| 国产一区成人| 色呦色呦色精品| 十大黄色软件免费看| 无遮挡aaaaa大片免费看| 国产在线欧美在线| 一本到一区二区三区| 在线免费看av片| 手机免费av片| 欧美亚洲视频在线观看| 午夜免费看视频| 5g影院5g天天爽永久免费影院| 国产丝袜精品视频| 国产探花视频在线播放| 精品丰满人妻无套内射| 亚洲黄网在线观看| 国产一区二区三区奇米久涩| 咪咪色在线视频| 国产免费区一区二区三视频免费| 色成年激情久久综合| 麻豆91在线播放| 玖草视频在线观看| 中文字幕在线久热精品| 久久久久久久久久av| 高潮毛片又色又爽免费| 日韩三级视频在线播放| 丝袜诱惑制服诱惑色一区在线观看| 一级二级三级在线观看| 一二三四社区欧美黄| 日本不卡高清| 一本一道精品欧美中文字幕| 亚洲乱妇老熟女爽到高潮的片| 亚洲一区二区色| 国产精品美女呻吟| 日韩一区二区三区视频在线观看| 国产永久免费视频| 青柠在线影院观看日本| 国产一级做a爰片在线看免费| 日韩一级在线观看| 色综合天天综合网天天狠天天| 久久精品日韩| 91精品免费久久久久久久久| 精品少妇一区二区| 日本电影在线观看网站| 欧美视频在线视频精品| 激情se五月| 欧美一级高清大全免费观看| 91精品产国品一二三产区| 久久综合国产精品台湾中文娱乐网| 精品亚洲aⅴ乱码一区二区三区| 亚洲一区二区网站| 成人频在线观看| 午夜3点看的视频| 色偷偷噜噜噜亚洲男人的天堂| 91国拍精品国产粉嫩亚洲一区| 婷婷综合久久中文字幕蜜桃三电影| 亚洲国产精品久| 亚欧美中日韩视频| 麻豆av电影| 国产日韩欧美一区在线| 日韩成人午夜影院| 午夜免费久久看| 日韩欧美精品综合| 欧美视频中文字幕在线| www.欧美亚洲| 国产无遮挡又黄又爽| 亚洲高清一区二| 丰满岳乱妇dvd日本| 亚洲午夜国产成人av电影男同| 污片在线免费看| 中文字幕在线2021| 黑人巨大精品一区二区在线| 99久久久久国产精品| 97国产真实伦对白精彩视频8| 欧美特级限制片免费在线观看| 午夜精品久久久久久久久久久| 欧美日韩国产综合一区二区三区| 日韩视频免费直播| 国产在线观看福利| 久久这里只精品| 不卡中文字幕在线| 视频在线观看国产精品| a级高清视频欧美日韩| 欧美国产精品一区二区| 肉色丝袜一区二区| 美国黄色a级片| 欧美乱妇高清无乱码| 欧美妇女性影城| 国产一区二区电影在线观看|