精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Sourcery 的 Swift Package 命令行插件

移動開發 iOS
當使用此新的 Camera service? 進行單元測試時,我們希望確保 AVCaptureSession? 沒有被真的創建。我們僅僅希望確認 camera service? 被測試系統(SUT)正確的調用了,而不是去測試 camera service 本身。

什么是Sourcery?

Sourcery 是當下最流行的 Swift 代碼生成工具之一。其背后使用了 SwiftSyntax[1],旨在通過自動生成樣板代碼來節省開發人員的時間。Sourcery 通過掃描一組輸入文件,然后借助模板的幫助,自動生成模板中定義的 Swift 代碼。

示例

考慮一個為攝像機會話服務提供公共 API 的協議:

protocol Camera {
func start()
func stop()
func capture(_ completion: @escaping (UIImage?) -> Void)
func rotate()
}

當使用此新的 Camera service 進行單元測試時,我們希望確保 AVCaptureSession 沒有被真的創建。我們僅僅希望確認 camera service 被測試系統(SUT)正確的調用了,而不是去測試 camera service 本身。

因此,創建一個協議的 mock 實現,使用空方法和一組變量來幫助我們進行單元測試,并斷言(asset)進行了正確的調用是有意義的。這是軟件開發中非常常見的一個場景,如果你曾維護過一個包含大量單元測試的大型代碼庫,這么做也可能有點乏味。

好吧~不用擔心!Sourcery 會幫助你!?? 它有一個叫做 AutoMockable[2] 的模板,此模板會為任意輸入文件中遵守 AutoMockable 協議的協議生成 mock 實現。

注意:在本文中,我擴展地使用了術語 Mock,因為它與 Sourcery 模板使用的術語一致。Mock 是一個相當重載的術語,但通常,如果我要創建一個 雙重測試[3],我會根據它的用途進一步指定類型的名稱(可能是 Spy 、 Fake 、 Stub 等)。如果您有興趣了解更多關于雙重測試的信息,馬丁·福勒(Martin Fowler)有一篇非常好的文章,可以解釋這些差異。

現在,我們讓 Camera 遵守 AutoMockable。該接口的唯一目的是充當 Sourcery 的目標,從中查找并生成代碼。

import UIKit

// Protocol to be matched
protocol AutoMockable {}

public protocol Camera: AutoMockable {
func start()
func stop()
func capture(_ completion: @escaping (UIImage?) -> Void)
func rotate()
}

此時,可以在上面的輸入文件上運行 Sourcery 命令,指定 AutoMockable 模板的路徑:

sourcery --sources Camera.swift --templates AutoMockable.stencil --output .

本文通過提供一個 .sourcery.yml 文件來配置 Sourcery 插件。如果提供了配置文件或 Sourcery 可以找到配置文件,則將忽略與其值沖突的所有命令行參數。如果您想了解有關配置文件的更多信息,Sourcery的 repo 中有一節[4]介紹了該主題。

命令執行完畢后,在輸出目錄下會生成一個 模板名 加 .generated.swift 為后綴的文件。在此例是 ./AutoMockable.generated.swift:

// Generated using Sourcery 1.8.2 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable line_length
// swiftlint:disable variable_name

import Foundation
#if os(iOS) || os(tvOS) || os(watchOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif

class CameraMock: Camera {

//MARK: - start

var startCallsCount = 0
var startCalled: Bool {
return startCallsCount > 0
}
var startClosure: (() -> Void)?

func start() {
startCallsCount += 1
startClosure?()
}

//MARK: - stop

var stopCallsCount = 0
var stopCalled: Bool {
return stopCallsCount > 0
}
var stopClosure: (() -> Void)?

func stop() {
stopCallsCount += 1
stopClosure?()
}

//MARK: - capture

var captureCallsCount = 0
var captureCalled: Bool {
return captureCallsCount > 0
}
var captureReceivedCompletion: ((UIImage?) -> Void)?
var captureReceivedInvocations: [((UIImage?) -> Void)] = []
var captureClosure: ((@escaping (UIImage?) -> Void) -> Void)?

func capture(_ completion: @escaping (UIImage?) -> Void) {
captureCallsCount += 1
captureReceivedCompletion = completion
captureReceivedInvocations.append(completion)
captureClosure?(completion)
}

//MARK: - rotate

var rotateCallsCount = 0
var rotateCalled: Bool {
return rotateCallsCount > 0
}
var rotateClosure: (() -> Void)?

func rotate() {
rotateCallsCount += 1
rotateClosure?()
}

}

上面的文件(AutoMockable.generated.swift)包含了你對mock的期望:使用空方法實現與目標協議的一致性,以及檢查是否調用了這些協議方法的一組變量。最棒的是… Sourcery 為您編寫了這一切!??

怎么運行 Sourcery?

怎么使用 Swift package 運行 Sourcery?

至此你可能在想如何以及怎樣在 Swift package 中運行 Sourcery。你可以手動執行,然后講文件拖到包中,或者從包目錄中的命令運行腳本。但是對于 Swift Package 有兩種內置方式運行可執行文件:

  1. 通過命令行插件,可根據用戶輸入任意運行
  2. 通過構建工具插件,該插件作為構建過程的一部分運行。

在本文中,我將介紹 Sourcery 命令行插件,但我已經在編寫第二部分,其中我將創建構建工具插件,這帶來了許多有趣的挑戰。

創建插件包

讓我們首先創建一個空包,并去掉測試和其他我們現在不需要的文件夾。然后我們可以創建一個新的插件 ??Target?? 并添加 Sourcery 的二進制文件作為其依賴項。

為了讓消費者使用這個插件,它還需要被定義為一個產品:

// swift-tools-version: 5.6
import PackageDescription

let package = Package(
name: "SourceryPlugins",
products: [
.plugin(name: "SourceryCommand", targets: ["SourceryCommand"])
],
targets: [
// 1
.plugin(
name: "SourceryCommand",
// 2
capability: .command(
intent: .custom(verb: "sourcery-code-generation", description: "Generates Swift files from a given set of inputs"),
// 3
permissions: [.writeToPackageDirectory(reason: "Need access to the package directory to generate files")]
),
dependencies: ["Sourcery"]
),
// 4
.binaryTarget(
name: "Sourcery",
path: "Sourcery.artifactbundle"
)
]
)

讓我們一步一步地仔細查看上面的代碼:

  1. 定義插件目標。
  2. 以custom 為意圖,定義了 .command 功能,因為沒有任何默認功能( documentationGeneration 和 sourceCodeFormatting)與該命令的用例匹配。給動詞一個合理的名稱很重要,因為這是從命令行調用插件的方式。
  3. 插件需要向用戶請求寫入包目錄的權限,因為生成的文件將被轉儲到該目錄。
  4. 為插件定義了一個二進制目標文件。這將允許插件通過其上下文訪問可執行文件。

我知道我并沒有詳細介紹上面的一些概念,但如果您想了解更多關于命令插件的信息,這里有一篇由 Tibor B?decs 寫的超級棒的文章?。如果你還想了解更多關于 Swift Packages 中二級制的目標(文件),我同樣有一篇??現今 Swift 包中的二進制目標??。

編寫插件

現在已經創建了包,是時候編寫一些代碼了!我們首先在 Plugins/SourceryCommand 下創建一個名為 SourceryCommand.swift 的文件,然后添加一個 CommandPlugin 協議的結構體,這將作為該插件的入口:

import PackagePlugin
import Foundation

@main
struct SourceryCommand: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {

}
}

然后我們為命令編寫實現:

func performCommand(context: PluginContext, arguments: [String]) async throws {
// 1
let configFilePath = context.package.directory.appending(subpath: ".sourcery.yml").string
guard FileManager.default.fileExists(atPath: configFilePath) else {
Diagnostics.error("Could not find config at: \(configFilePath)")
return
}
//2
let sourceryExecutable = try context.tool(named: "sourcery")
let sourceryURL = URL(fileURLWithPath: sourceryExecutable.path.string)

// 3
let process = Process()
process.executableURL = sourceryURL

// 4
process.arguments = [
"--disableCache"
]
// 5
try process.run()
process.waitUntilExit()

// 6
let gracefulExit = process.terminationReason == .exit && process.terminationStatus == 0
if !gracefulExit {
Diagnostics.error("?? The plugin execution failed")
}
}

讓我們仔細看看上面的代碼:

  1. 首先.sourcery.yml 文件必須在包的根目錄,否則將報錯。這將使 Sourcery 神奇的工作,并使包可配置。
  2. 可執行文件路徑的 URL 是從命令的上下文中檢索的。
  3. 創建一個進程,并將 Sourcery 的可執行文件的 URL 設置為其可執行文件路徑。
  4. 這一步有點麻煩。Sourcery 使用緩存來減少后續運行的代碼生成時間,但問題是這些緩存是在包文件夾之外讀取和寫入的文件。插件的沙箱規則不允許這樣做,因此--disableCache 標志用于禁用此行為并允許命令運行。
  5. 進程同步運行并等待。
  6. 最后,檢查進程終止狀態和代碼,以確保進程已正常退出。在任何其他情況下,通過Diagnostics API 向用戶告知錯誤。

就這樣!現在讓我們使用它

使用(插件)包

考慮一個用戶正在使用插件,該插件將依賴項引入了他們的 Package.swift 文件:

// swift-tools-version: 5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "SourceryPluginSample",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "SourceryPluginSample",
targets: ["SourceryPluginSample"]),
],
dependencies: [
.package(url: "https://github.com/pol-piella/sourcery-plugins.git", branch: "main")
],
targets: [
.target(
name: "SourceryPluginSample",
dependencies: [],
exclude: ["SourceryTemplates"]
),
]
)

 注意,與構建工具插件不同,命令插件不需要應用于任何目標,因為它們需要手動運行。

用戶只使用了上面的 AutoMockable 模板(可以在 Sources/SourceryPluginSample/SourceryTemplates 下找到),與本文前面顯示的示例相匹配:

protocol AutoMockable {}

protocol Camera: AutoMockable {
func start()
func stop()
func capture(_ completion: @escaping (UIImage?) -> Void)
func rotate()
}

根據插件的要求,用戶還提供了一個位于 SourceryPluginSample 目錄下的 .sourcery.yml 配置文件:

sources:
- Sources/SourceryPluginSample
templates:
- Sources/SourceryPluginSample/SourceryTemplates
output: Sources/SourceryPluginSample

運行命令

用戶已經設置好了,但是他們現在如何運行包??? 有兩種方法:

命令行

運行插件的一種方法是用命令行??梢酝ㄟ^從包目錄中運行 swift package plugin --list 來檢索特定包的可用插件列表。然后可以從列表中選擇一個包,并通過運行 swift package <command's verb> 來執行,在這個特殊的例子中,運行: swift package sourcery-code-generation。

注意,由于此包需要特殊權限,因此 --allow-writing-to-package-directory 必須與命令一起使用。

此時,你可能會想,為什么我要費心編寫一個插件,仍然必須從命令行運行,而我可以用一個簡單的腳本在幾行 bash 中完成相同的工作?好吧,讓我們來看看 Xcode 14 中會出現什么,你會明白為什么我會提倡編寫插件??。

Xcode

這是運行命令插件最令人興奮的方式,但不幸的是,它僅在 Xcode 14 中可用。因此,如果您需要運行命令,但尚未使用 Xcode 14,請參閱命令行部分。

如果你正好在使用 Xcode 14,你可以通過在文件資源管理器中右鍵單擊包,從列表中找到要執行的插件,然后單擊它來執行包的任何命令。

下一步

這是插件的初始實現。我將研究如何改進它,使它更加健壯。和往常一樣,我非常致力于公開構建,并使我的文章中的所有內容都開源,這樣任何人都可以提交問題或創建任何具有改進或修復的 PRs。這沒有什么不同??, 這是 公共倉庫的鏈接。

此外,如果您喜歡這篇文章,請關注即將到來的第二部分,其中我將制作一個 Sourcery 構建工具插件。我知道這聽起來不多,但這不是一項容易的任務!

參考資料

[1] SwiftSyntax: ??https://github.com/apple/swift-syntax。??

[2] AutoMockable: ??https://github.com/krzysztofzablocki/Sourcery/blob/master/Templates/Templates/AutoMockable.stencil。??

[3] 雙重測試: ??https://en.wikipedia.org/wiki/Test_double。??

[4] repo: ??https://github.com/krzysztofzablocki/Sourcery/blob/master/guides/Usage.md#configuration-file。??

責任編輯:姜華 來源: Swift社區
相關推薦

2016-03-28 10:00:09

Swift命令程序

2022-08-10 09:02:08

SwiftDecodable

2015-07-01 09:15:46

linuxQuora命令行

2023-08-01 13:31:18

模型Alpacaicuna

2020-12-11 06:44:16

命令行工具開發

2020-12-10 16:16:08

工具代碼開發

2011-01-18 19:11:26

Postfix命令行

2010-11-16 11:50:21

oracle命令行登錄

2012-02-08 16:37:36

ibmdw

2010-07-15 10:47:22

Perl命令行

2010-03-10 17:23:37

Python 命令行參

2009-12-24 14:51:39

Linux命令行

2020-12-06 08:00:46

scanimage命令行Linux

2023-06-09 07:45:29

Kuberneteskubectl

2010-07-20 14:18:22

Perl命令行

2010-07-15 09:37:47

Perl命令行

2019-07-23 13:45:38

LinuxFedora權限

2009-07-20 09:55:30

華為命令行解析華為認證

2010-08-20 10:05:23

用戶命令

2010-09-01 14:23:54

Linux命令行開發
點贊
收藏

51CTO技術棧公眾號

狠狠操精品视频| 91精品免费| 国产不卡在线观看视频| 在线成人免费| 亚洲成av人片在线观看| 欧洲精品久久| 国产手机精品视频| 午夜亚洲性色福利视频| 中文字幕亚洲天堂| 成人啪啪18免费游戏链接| 免费成人动漫| 亚洲激情六月丁香| 欧美一区二区三区成人久久片| 亚洲最新av网站| 伊人狠狠色j香婷婷综合| 亚洲桃花岛网站| 师生出轨h灌满了1v1| 都市激情亚洲一区| 亚洲精选在线视频| 欧美一区1区三区3区公司| 99久久精品日本一区二区免费| 亚洲专区欧美专区| 久久夜色精品亚洲噜噜国产mv| 三上悠亚影音先锋| 成人18夜夜网深夜福利网| 欧美日韩午夜剧场| 老司机午夜免费福利视频| 三级视频在线播放| 国产成人福利片| 91精品久久久久久久久久入口 | 99精品视频精品精品视频 | 国产高清一区在线观看| 国产精品69久久久久水密桃| 国产精品久久久久久久久久尿 | av男人的天堂在线观看| 中文字幕av资源一区| 国产精品国产精品国产专区蜜臀ah| 在线观看国产区| 国产欧美69| 久久免费高清视频| 免费又黄又爽又色的视频| 91久久夜色精品国产按摩| 亚洲另类图片色| 荫蒂被男人添免费视频| 我要色综合中文字幕| 777久久久精品| 天天干天天玩天天操| 三妻四妾的电影电视剧在线观看| 亚洲高清免费一级二级三级| 欧美美女黄色网| av免费网站在线观看| 中文字幕一区二区在线观看| 四虎影视永久免费在线观看一区二区三区| 三区在线观看| 91蜜桃免费观看视频| 久久国产精品精品国产色婷婷| 秋霞欧美在线观看| 成人99免费视频| 国产精品美女久久久久av福利| 亚洲精品久久久久久久久久 | 国产精品久久亚洲7777| 亚洲精品视频91| 高清av一区二区| 国产一区在线免费观看| 四季av日韩精品一区| 99re亚洲国产精品| 明星裸体视频一区二区| 精品福利视频导航大全| 欧美激情在线看| 亚洲五月六月| 在线heyzo| 亚洲国产精品久久久久婷婷884| 男女日批视频在线观看| av中文在线资源库| 色综合网色综合| 天天视频天天爽| 国产精品视频一区二区三区| 日韩欧美亚洲国产精品字幕久久久| 中文字幕在线视频一区二区| 57pao国产一区二区| 亚洲激情视频网站| 亚洲第一香蕉网| 欧美成人精品一区二区三区在线看| 日韩中文字幕久久| 久艹视频在线观看| 午夜影院日韩| 成人黄色片网站| 国产麻豆精品一区| 99re这里只有精品6| 日韩欧美视频一区二区三区四区| 国产写真视频在线观看| 亚洲丰满少妇videoshd| 成人三级视频在线播放 | 在线播放日韩导航| www国产视频| 成人免费电影网址| 欧美精品www| 337p粉嫩色噜噜噜大肥臀| 久久er精品视频| 国产一区二区三区色淫影院| 国产黄在线看| 亚洲国产精品人人做人人爽| 久久午夜夜伦鲁鲁一区二区| 色播一区二区| 国产亚洲欧洲高清| 免费在线观看黄色av| 日本欧美一区二区| 国产一区二区免费电影| 日韩成人影视| 欧美视频在线视频| 制服丝袜中文字幕第一页| 琪琪久久久久日韩精品| 精品久久久91| 无码人妻精品一区二区蜜桃色欲| 国产成人亚洲精品狼色在线| 神马影院午夜我不卡| 91超碰国产在线| 91精品黄色片免费大全| 人妻少妇无码精品视频区| 韩日欧美一区| 91视频国产一区| 成人高清网站| 欧美性xxxxx极品| 午夜不卡久久精品无码免费| 亚洲精品在线观看91| 日韩av片永久免费网站| 国产小视频一区| 亚洲欧美在线视频| 日本www高清视频| 日韩电影在线观看完整免费观看| 欧美国产日韩xxxxx| 一级黄色大片免费| 久久精子c满五个校花| www.射射射| 成人精品毛片| 欧美精品xxx| 免费a级片在线观看| 亚洲欧美日韩电影| 国产永久免费网站| 三级电影一区| 国产欧美亚洲视频| 国产三级视频在线播放线观看| 精品久久久久久久大神国产| 免费不卡的av| 好看不卡的中文字幕| 亚洲一区二区少妇| v片在线观看| 日韩欧美在线观看一区二区三区| 免费一级suv好看的国产网站 | 国产精品偷伦免费视频观看的| 色吊丝在线永久观看最新版本| 精品久久久中文| 天天躁日日躁狠狠躁av麻豆男男 | 日韩欧美影院| 97精品国产aⅴ7777| 欧美熟妇乱码在线一区| 亚洲成人免费看| 成人手机在线免费视频| 9国产精品视频| 久久久久久国产精品mv| 天堂中文在线播放| 亚洲久久久久久久久久| 国产午夜无码视频在线观看| 欧美国产综合色视频| 在线看的黄色网址| 99久久综合| 91丝袜脚交足在线播放| 国产一线二线在线观看| 亚洲国产日韩欧美在线99| 日韩在线视频免费播放| 国产日韩精品一区| 超碰在线资源站| 伊人久久成人| 日本精品一区| 国产精品一区二区三区av| 久久99热精品这里久久精品| 天堂av资源网| 欧美色涩在线第一页| 在线看的片片片免费| 成人免费观看av| 老熟妇仑乱视频一区二区| 天天影视欧美综合在线观看| 国产精品.com| 三级成人黄色影院| 久久在线免费观看视频| 香港三日本三级少妇66| 欧美三级韩国三级日本一级| 免费在线观看日韩| 久久精品欧美一区二区三区麻豆| 亚洲精品手机在线观看| 亚洲麻豆av| 永久免费精品视频网站| 成人在线超碰| 国产三级精品网站| 91豆花视频在线播放| 一本一本久久a久久精品综合小说| 国产露脸无套对白在线播放| 午夜精品一区二区三区电影天堂| 久久免费手机视频| 成人av电影在线网| 中文字幕日韩综合| 国产欧美日韩综合一区在线播放| 一区二区三区在线视频看| 亲子伦视频一区二区三区| 91久久久久久久久久| 亚洲美女久久精品| 欧美日韩xxx| 在线播放麻豆| 亚洲精品乱码久久久久久按摩观| 91久久精品国产91性色69 | 美女福利精品视频| 国产在线超碰| 亚洲精品97久久| 99在线观看精品视频| 日本精品视频一区二区三区| 久久免费精彩视频| 亚洲婷婷综合久久一本伊一区| 国产精品久久不卡| 国产a级毛片一区| 国产成人美女视频| 久久只有精品| 99999精品视频| 亚洲人人精品| 性一交一乱一伧国产女士spa| 国产精品久久占久久| 日韩理论片在线观看| 秋霞在线一区| 国内视频一区二区| 91精品短视频| 91精品国产99久久久久久红楼| 免费日韩成人| 国产精品免费电影| 欧美男女交配| 欧美在线视频一二三| 激情黄产视频在线免费观看| 久久久噜噜噜久久中文字免| 污视频免费在线观看| 久久成年人免费电影| 好了av在线| 久久亚洲春色中文字幕| 欧美a免费在线| 日韩中文字幕av| 欧美日韩在线资源| 色偷偷av一区二区三区| 97在线观看免费观看高清| 亚洲一区二区久久| 2021av在线| 日韩在线免费高清视频| 日本中文字幕视频在线| www.亚洲免费视频| 国产激情在线视频| 免费91麻豆精品国产自产在线观看 | 欧美成人黄色| 国产在线播放91| 国内精品视频| 国产精品乱码视频| 色婷婷精品视频| 日本精品一区二区三区高清 久久| 欧美猛男同性videos| 青青成人在线| 国产韩日影视精品| 一本大道东京热无码aⅴ| 午夜视频精品| 久操网在线观看| 可以看av的网站久久看| 99热手机在线| 国产一区二区三区在线观看精品| 色网站在线视频| 成人免费视频一区| 性少妇bbw张开| 中文字幕一区二区三区在线播放| 青娱乐国产在线| 疯狂欧美牲乱大交777| 波多野结衣视频免费观看| 欧美美女视频在线观看| wwwav在线播放| 亚洲码在线观看| 一级日本在线| 久久久久久久国产精品视频| 欧美xxx网站| 成人中文字幕+乱码+中文字幕| jizzjizzjizz欧美| 日韩电影免费观看在| 综合一区二区三区| 免费无码毛片一区二三区| 奇米影视一区二区三区| 中文av一区二区三区| 极品尤物av久久免费看| 丰满人妻一区二区三区免费视频棣| 99视频精品免费视频| 91禁男男在线观看| 亚洲高清久久久| 在线观看日韩一区二区| 亚洲精品一区二区三区99| 毛片在线播放网站| 九色精品免费永久在线| 黄瓜视频成人app免费| 97人人模人人爽视频一区二区 | 日本福利视频导航| 亚洲欧美网站| 亚洲熟妇一区二区| 中文文精品字幕一区二区| 黄色一级片在线| 欧美日韩一级二级三级| 欧日韩在线视频| 欧美成人激情图片网| 香蕉视频亚洲一级| 成人毛片网站| 99成人在线视频| 无遮挡又爽又刺激的视频| 国产99精品在线观看| 日本爱爱小视频| 在线视频综合导航| 婷婷伊人综合中文字幕| 久久综合网hezyo| 精品久久在线| 欧美久久在线| 亚洲激情网址| 中文在线字幕观看| 亚洲免费在线视频| 中国女人真人一级毛片| 日韩精品在线观看一区| 久久不射影院| 91精品入口蜜桃| 亚洲一区二区日韩| 伊人成人222| 国产精品嫩草久久久久| 亚洲 欧美 中文字幕| 日韩av在线最新| 草草视频在线| 国产精品一区二区三区在线| 午夜欧美精品| 古装做爰无遮挡三级聊斋艳谭| 国产精品久99| 一级做a爱片性色毛片| 正在播放亚洲1区| 麻豆精品蜜桃| 日韩欧美手机在线| 日韩中文字幕91| www.狠狠爱| 色激情天天射综合网| 九一国产在线| 国产精品久久久久久久久久新婚| 久久综合欧美| 国产成人手机视频| 亚洲国产精品t66y| 岳乳丰满一区二区三区| 中文字幕亚洲一区| 国产剧情一区二区在线观看| 午夜啪啪福利视频| 国产麻豆精品久久一二三| 日本少妇高清视频| 精品精品欲导航| 韩日毛片在线观看| 蜜桃精品久久久久久久免费影院| 午夜亚洲精品| 黄色一级片一级片| 欧美丰满一区二区免费视频| 91一区二区三区在线| 国产不卡一区二区三区在线观看| 亚洲黄色视屏| 欧洲女同同性吃奶| 欧美视频你懂的| 成年人网站在线| 狠狠色噜噜狠狠色综合久| 国产精品久久久久久模特| 人妻一区二区视频| 欧美猛男男办公室激情| 日本三级韩国三级欧美三级| 精品国产乱码久久久久久108| 久久精品免费| 我要看黄色一级片| 欧美精品一区二区久久婷婷| 日韩成人影音| 日韩第一页在线观看| 成人精品国产免费网站| 麻豆精品久久久久久久99蜜桃| 中文字幕亚洲综合久久| 一区二区在线免费播放| www.亚洲天堂网| 自拍偷在线精品自拍偷无码专区 | 成人av在线资源网站| 青青草免费观看视频| 日韩在线观看av| 嫩草国产精品入口| 中文字幕第38页| 欧美日韩亚洲成人| 免费高清完整在线观看| 国产一区国产精品| 精品一区二区免费| 日本免费观看视| 久久精品成人一区二区三区| 久久a爱视频| 91热视频在线观看| 欧美日韩中文字幕在线视频| 色哟哟免费在线观看 | 性久久久久久久久久久久久久| 舔着乳尖日韩一区| 九七电影韩国女主播在线观看| 蜜桃91精品入口|