# Copyright 2014 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License. """
Tests database migration scripts for mysql. To run the tests, you'll need to set up db user named 'openstack_citest'
with password 'openstack_citest' on localhost. This user needs db
admin rights (i.e. create/drop database) """
import glob
import os import migrate.versioning.api as migration_api
from migrate.versioning import repository
from oslo_concurrency import processutils
from oslo_log import log as logging
from proboscis import after_class
from proboscis.asserts import assert_equal
from proboscis.asserts import assert_true
from proboscis import before_class
from proboscis import SkipTest
from proboscis import test
import sqlalchemy
import sqlalchemy.exc from trove.common.i18n import _
import trove.db.sqlalchemy.migrate_repo
from trove.tests.util import event_simulator GROUP = "dbaas.db.migrations"
LOG = logging.getLogger(__name__) @test(groups=[GROUP])
class ProjectTestCase(object):
"""Test migration scripts integrity.""" @test
def test_all_migrations_have_downgrade(self):
topdir = os.path.normpath(os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir))
py_glob = os.path.join(topdir, "trove", "db", "sqlalchemy",
"migrate_repo", "versions", "*.py") missing_downgrade = []
for path in glob.iglob(py_glob):
has_upgrade = False
has_downgrade = False
with open(path, "r") as f:
for line in f:
if 'def upgrade(' in line:
has_upgrade = True
if 'def downgrade(' in line:
has_downgrade = True if has_upgrade and not has_downgrade:
fname = os.path.basename(path)
missing_downgrade.append(fname) helpful_msg = (_("The following migration scripts are missing a "
"downgrade implementation:\n\t%s") %
'\n\t'.join(sorted(missing_downgrade)))
assert_true(not missing_downgrade, helpful_msg) @test(depends_on_classes=[ProjectTestCase],
groups=[GROUP])
class TestTroveMigrations(object):
"""Test sqlalchemy-migrate migrations."""
USER = "openstack_citest"
PASSWD = "openstack_citest"
DATABASE = "openstack_citest" @before_class
def setUp(self):
event_simulator.allowable_empty_sleeps = 1 @after_class
def tearDown(self):
event_simulator.allowable_empty_sleeps = 0 def __init__(self):
self.MIGRATE_FILE = trove.db.sqlalchemy.migrate_repo.__file__
self.REPOSITORY = repository.Repository(
os.path.abspath(os.path.dirname(self.MIGRATE_FILE)))
self.INIT_VERSION = 0 def _get_connect_string(self, backend, database=None):
"""Get database connection string."""
args = {'backend': backend,
'user': self.USER,
'passwd': self.PASSWD}
template = "%(backend)s://%(user)s:%(passwd)s@localhost"
if database is not None:
args['database'] = database
template += "/%(database)s"
return template % args def _is_backend_avail(self, backend):
"""Check database backend availability."""
connect_uri = self._get_connect_string(backend)
engine = sqlalchemy.create_engine(connect_uri)
try:
connection = engine.connect()
except Exception:
# any error here means the database backend is not available
return False
else:
connection.close()
return True
finally:
if engine is not None:
engine.dispose() def _execute_cmd(self, cmd=None):
"""Shell out and run the given command."""
out, err = processutils.trycmd(cmd, shell=True)
# Until someone wants to rewrite this to avoid the warning
# we need to handle it for newer versions of mysql
valid_err = err == '' or \
err == 'mysql: [Warning] Using a password on the ' \
'command line interface can be insecure.\n'
assert_true(valid_err,
"Failed to run: '%(cmd)s' "
"Output: '%(stdout)s' "
"Error: '%(stderr)s'" %
{'cmd': cmd, 'stdout': out, 'stderr': err}) def _reset_mysql(self):
"""Reset the MySQL test database Drop the MySQL test database if it already exists and create
a new one.
"""
sql = ("drop database if exists %(database)s; "
"create database %(database)s;" % {'database': self.DATABASE})
cmd = ("mysql -u \"%(user)s\" -p%(password)s -h %(host)s "
"-e \"%(sql)s\"" % {'user': self.USER, 'password': self.PASSWD,
'host': 'localhost', 'sql': sql})
self._execute_cmd(cmd) @test
def test_mysql_migration(self):
db_backend = "mysql+pymysql"
# Gracefully skip this test if the developer do not have
# MySQL running. MySQL should always be available on
# the infrastructure
if not self._is_backend_avail(db_backend):
raise SkipTest("MySQL is not available.")
self._reset_mysql()
connect_string = self._get_connect_string(db_backend, self.DATABASE)
engine = sqlalchemy.create_engine(connect_string)
self._walk_versions(engine)
engine.dispose() def _walk_versions(self, engine=None): //跑版本
"""Walk through and test the migration scripts Determine latest version script from the repo, then
upgrade from 1 through to the latest, then downgrade from
the latest back to 1, with no data in the databases. This
just checks that the schema itself upgrades and downgrades
successfully.
"""
# Place the database under version control
migration_api.version_control(engine, self.REPOSITORY,
self.INIT_VERSION)
assert_equal(self.INIT_VERSION,
migration_api.db_version(engine, self.REPOSITORY)) LOG.debug('Latest version is %s' % self.REPOSITORY.latest)
versions = range(self.INIT_VERSION + 1, self.REPOSITORY.latest + 1) //从最开始的那版跑到最新那版+1终止,INIT_VERSION初始值是0,所以要+ 1,range函数的终止是后面那个参数,但不会到那个参数,相当于++i # Snake walk from version 1 to the latest, testing the upgrade paths.
# upgrade -> downgrade -> upgrade
for version in versions:
self._migrate_up(engine, version)
self._migrate_down(engine, version - 1)
self._migrate_up(engine, version) # Now snake walk back down to version 1 from the latest, testing the
# downgrade paths.
# downgrade -> upgrade -> downgrade
for version in reversed(versions):
self._migrate_down(engine, version - 1)
self._migrate_up(engine, version)
self._migrate_down(engine, version - 1) def _migrate_down(self, engine, version): //版本往上跑
"""Migrate down to an old version of database."""
migration_api.downgrade(engine, self.REPOSITORY, version)
assert_equal(version,
migration_api.db_version(engine, self.REPOSITORY)) def _migrate_up(self, engine, version): //版本往下跑
"""Migrate up to a new version of database."""
migration_api.upgrade(engine, self.REPOSITORY, version)
assert_equal(version,
migration_api.db_version(engine, self.REPOSITORY)) 这个文件感觉大部分就是在做版本的问题,看看升级版本或者降级版本的时候,数据是不是会被破坏,我是这么理解的。。。
trove,测试,db小解析的更多相关文章
-
屠龙之路_击败DB小boss_FifthDay
摘要:服务器大魔王被击败的消息传到了恶龙boss那里,恶龙大怒派出了自己的首级大将DB人称小boss,但小boss的名号并没有吓到七位屠龙勇士,经过他们齐心协力的进攻,最终击败了DB,小boss临死前 ...
-
使用Appium 测试微信小程序和微信公众号方法
由于腾讯系QQ.微信等都是基于腾讯自研X5内核,不是google原生webview,需要打开TBS内核Inspector调试功能才能用Chrome浏览器查看页面元素,并实现Appium自动化测试微信小 ...
-
Appium之测试微信小程序
坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:Oschina.云+社区.知乎等各大平台都有. 目录 一.往期回顾 二.测试微信小程序 1.准备工作 2.操作步骤 3.注意 4.强制设置安卓的进程 ...
-
ESA2GJK1DH1K微信小程序篇: 测试微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备
前言(源码使用介绍在最后) 一,微信小程序篇小程序下载(该源码为这节测试源代码) 二.有多少人一直在期盼着小程序可以实现SmartConfig或者Airkiss的功能? 来吧!我的这种方式包您满意. ...
-
Miller-Rabin素数测试学习小计
1.Miller-Rabin是干啥的?它是用来检测一个数字(一般是很大的数字)是不是素数: 2.Miller-Rabin算法基于的两个定理: (1)费尔马小定理:如果p是一个素数,且0<a< ...
-
fastJson解析复杂的json字符串,经测试已经成功解析
要解析的json数据格式为: HTTP/1.1 200 OK Content-Type: text/jsv Content-Length: length { ResponseStatus: { }, ...
-
自己动手编写IPv4地址包含关系测试的小脚本
工作中需要对地址包含关系进行测试,现有ipaddress标准库和IPy无法满足,于是自己动手编写小脚本,主要实现== , in, <等专用功能,其他功能可以后续用到再补充,例如迭代打印网段内所有 ...
-
java对象传递小解析
先上代码: import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder ...
-
Web进行压力测试的小工具
在Linux下对Web进行压力测试的小工具有很多,比较出名的有AB.虽然AB可以运行在windows下,但对于想简单界面操作的朋友有点不太习惯.其实vs.net也提供压力测试功能但显然显得太重了,在测 ...
随机推荐
-
CURL in windows
目前版本为: 7.50.3 >> 不同操作系统及版本的下载页面 https://curl.haxx.se/download/?C=M;O=D Windows上的下载入口及地址为: htt ...
-
sicily 1007. To and Fro 2016 11 02
// Problem#: 1007// Submission#: 4893204// The source code is licensed under Creative Commons Attrib ...
-
Oracle中关于bitmap index的使用问题
您如果熟悉 Oracle 数据库,我想您对 Thomas Kyte 的大名一定不会陌生. Tomas 主持的 asktom.oracle.com 网站享誉 Oracle 界数十年,绝非幸致.最近在图书 ...
-
HDU 5000
http://acm.hdu.edu.cn/showproblem.php?pid=5000 题意:有n种属性,每种属性的数值可以是0-T[i],当一个人属性全部小于等于另一个人的属性时,小的那个人会 ...
-
Eclipse 浏览文件插件 EasyExplorer 和 OpenExplorer
EasyExplorer 是一个类似于 Windows Explorer的Eclipse插件,它可以帮助你在不退出Eclipse的环境下浏览本地文件系统 下载地址: 从 http://sourcef ...
-
jdk8新特性之lambda expressions
本文分两部分: 语法简单说明 lambda的使用 注:这两部分内容均以类+注释的方式进行说明,并且内容均来自官方教程(https://docs.oracle.com/javase/tutorial/j ...
-
Python入门 - 控制结构
python控制结构有:for循环, while循环, if条件语句,下面我们直接上代码. 一.for循环 a = range(5) for x in a : print(x) 0 1 2 3 4二. ...
-
python:过滤字符串中的字母数字特殊符号
今天遇到的字符串处理的问题,记录一下方便使用 str1 = input('请输入一个字符:') #初始化字符.数字.空格.特殊字符的计数 lowercase = 0 uppercase = 0 num ...
-
sqlalchemy外键的一些东西
sqlalchemy中让MySQL支持中文字符 engine = create_engine("mysql+pymysql://root:mysql8@localhost/mysqltest ...
- learning makefile string example