Skip to content

Commit cd8a2ce

Browse files
author
aviau
committed
Ensure tests pass without influxdb bin
1 parent 9e40ef2 commit cd8a2ce

File tree

7 files changed

+235
-218
lines changed

7 files changed

+235
-218
lines changed

tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# -*- coding: utf-8 -*-
22
import unittest
33
import sys
4+
import os
45

56
using_pypy = hasattr(sys, "pypy_version_info")
67
skipIfPYpy = unittest.skipIf(using_pypy, "Skipping this test on pypy.")
8+
9+
_skip_server_tests = os.environ.get('INFLUXDB_PYTHON_SKIP_SERVER_TESTS', None) == 'True'
10+
skipServerTests = unittest.skipIf(_skip_server_tests, "Skipping server tests...")

tests/influxdb/server_tests/__init__.py

Whitespace-only changes.

tests/influxdb/server_tests/base.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import sys
4+
5+
from tests import using_pypy
6+
from tests.influxdb.server_tests.influxdb_instance import InfluxDbInstance
7+
8+
from influxdb.client import InfluxDBClient
9+
10+
if not using_pypy:
11+
from influxdb.dataframe_client import DataFrameClient
12+
13+
14+
def _setup_influxdb_server(inst):
15+
inst.influxd_inst = InfluxDbInstance(
16+
inst.influxdb_template_conf,
17+
udp_enabled=getattr(inst, 'influxdb_udp_enabled', False),
18+
)
19+
20+
inst.cli = InfluxDBClient('localhost',
21+
inst.influxd_inst.http_port,
22+
'root',
23+
'',
24+
database='db')
25+
if not using_pypy:
26+
inst.cliDF = DataFrameClient('localhost',
27+
inst.influxd_inst.http_port,
28+
'root',
29+
'',
30+
database='db')
31+
32+
33+
def _teardown_influxdb_server(inst):
34+
remove_tree = sys.exc_info() == (None, None, None)
35+
inst.influxd_inst.close(remove_tree=remove_tree)
36+
37+
38+
class SingleTestCaseWithServerMixin(object):
39+
''' A mixin for unittest.TestCase to start an influxdb server instance
40+
in a temporary directory **for each test function/case**
41+
'''
42+
43+
# 'influxdb_template_conf' attribute must be set
44+
# on the TestCase class or instance.
45+
46+
setUp = _setup_influxdb_server
47+
tearDown = _teardown_influxdb_server
48+
49+
50+
class ManyTestCasesWithServerMixin(object):
51+
''' Same than SingleTestCaseWithServerMixin
52+
but creates a single instance for the whole class.
53+
Also pre-creates a fresh database: 'db'.
54+
'''
55+
56+
# 'influxdb_template_conf' attribute must be set on the class itself !
57+
58+
@classmethod
59+
def setUpClass(cls):
60+
_setup_influxdb_server(cls)
61+
62+
def setUp(self):
63+
self.cli.create_database('db')
64+
65+
@classmethod
66+
def tearDownClass(cls):
67+
_teardown_influxdb_server(cls)
68+
69+
def tearDown(self):
70+
self.cli.drop_database('db')

tests/influxdb/client_test_with_server.py renamed to tests/influxdb/server_tests/client_test_with_server.py

Lines changed: 7 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,11 @@
1111
"""
1212

1313
from __future__ import print_function
14-
import datetime
15-
import distutils.spawn
14+
1615
from functools import partial
1716
import os
18-
import shutil
19-
import subprocess
20-
import sys
21-
import tempfile
2217
import time
2318
import unittest
24-
2519
import warnings
2620

2721
# By default, raise exceptions on warnings
@@ -30,50 +24,17 @@
3024
from influxdb import InfluxDBClient
3125
from influxdb.exceptions import InfluxDBClientError
3226

33-
from tests.influxdb.misc import get_free_port, is_port_open
34-
from tests import skipIfPYpy, using_pypy
27+
from tests import skipIfPYpy, using_pypy, skipServerTests
28+
from tests.influxdb.server_tests.base import ManyTestCasesWithServerMixin
29+
from tests.influxdb.server_tests.base import SingleTestCaseWithServerMixin
3530

3631
if not using_pypy:
3732
import pandas as pd
3833
from pandas.util.testing import assert_frame_equal
39-
from influxdb import DataFrameClient
4034

4135

4236
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
4337

44-
#############################################################################
45-
# try to find where the 'influxd' binary is located:
46-
# You can define 'InfluxDbPythonClientTest_SERVER_BIN_PATH'
47-
# env var to force it :
48-
influxdb_bin_path = influxdb_forced_bin = os.environ.get(
49-
'InfluxDbPythonClientTest_SERVER_BIN_PATH', '')
50-
if not influxdb_bin_path:
51-
try:
52-
influxdb_bin_path = distutils.spawn.find_executable('influxd')
53-
if not influxdb_bin_path:
54-
raise Exception('not found via distutils')
55-
except Exception as err:
56-
try:
57-
influxdb_bin_path = subprocess.check_output(
58-
['which', 'influxdb']).strip()
59-
except subprocess.CalledProcessError as err:
60-
# fallback on :
61-
influxdb_bin_path = '/opt/influxdb/influxd'
62-
63-
is_influxdb_bin_ok = (
64-
# if the env var is set then consider the influxdb_bin as OK..
65-
influxdb_forced_bin
66-
or (os.path.isfile(influxdb_bin_path)
67-
and os.access(influxdb_bin_path, os.X_OK))
68-
)
69-
70-
if is_influxdb_bin_ok:
71-
# read version :
72-
version = subprocess.check_output([influxdb_bin_path, 'version'])
73-
print(version, file=sys.stderr)
74-
75-
76-
#############################################################################
7738

7839
def point(serie_name, timestamp=None, tags=None, **fields):
7940
res = {'measurement': serie_name}
@@ -152,174 +113,7 @@ def point(serie_name, timestamp=None, tags=None, **fields):
152113
}
153114
]
154115

155-
#############################################################################
156-
157-
158-
class InfluxDbInstance(object):
159-
''' A class to launch of fresh influxdb server instance
160-
in a temporary place, using a config file template.
161-
'''
162-
163-
def __init__(self, conf_template, udp_enabled=False):
164-
# create a temporary dir to store all needed files
165-
# for the influxdb server instance :
166-
self.temp_dir_base = tempfile.mkdtemp()
167-
# "temp_dir_base" will be used for conf file and logs,
168-
# while "temp_dir_influxdb" is for the databases files/dirs :
169-
tempdir = self.temp_dir_influxdb = tempfile.mkdtemp(
170-
dir=self.temp_dir_base)
171-
# we need some "free" ports :
172-
173-
ports = dict(
174-
http_port=get_free_port(),
175-
admin_port=get_free_port(),
176-
meta_port=get_free_port(),
177-
udp_port=get_free_port() if udp_enabled else -1,
178-
)
179-
180-
conf_data = dict(
181-
meta_dir=os.path.join(tempdir, 'meta'),
182-
data_dir=os.path.join(tempdir, 'data'),
183-
cluster_dir=os.path.join(tempdir, 'state'),
184-
handoff_dir=os.path.join(tempdir, 'handoff'),
185-
logs_file=os.path.join(self.temp_dir_base, 'logs.txt'),
186-
udp_enabled='true' if udp_enabled else 'false',
187-
)
188-
conf_data.update(ports)
189-
self.__dict__.update(conf_data)
190-
191-
conf_file = os.path.join(self.temp_dir_base, 'influxdb.conf')
192-
with open(conf_file, "w") as fh:
193-
with open(conf_template) as fh_template:
194-
fh.write(fh_template.read().format(**conf_data))
195-
196-
# now start the server instance:
197-
proc = self.proc = subprocess.Popen(
198-
[influxdb_bin_path, '-config', conf_file],
199-
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
200-
201-
print("%s > Started influxdb bin in %r with ports %s and %s.." % (
202-
datetime.datetime.now(),
203-
self.temp_dir_base,
204-
self.admin_port, self.http_port))
205-
206-
# wait for it to listen on the broker and admin ports:
207-
# usually a fresh instance is ready in less than 1 sec ..
208-
timeout = time.time() + 10 # so 10 secs should be enough,
209-
# otherwise either your system load is high,
210-
# or you run a 286 @ 1Mhz ?
211-
try:
212-
while time.time() < timeout:
213-
if (is_port_open(self.http_port)
214-
and is_port_open(self.admin_port)):
215-
# it's hard to check if a UDP port is open..
216-
if udp_enabled:
217-
# so let's just sleep 0.5 sec in this case
218-
# to be sure that the server has open the port
219-
time.sleep(0.5)
220-
break
221-
time.sleep(0.5)
222-
if proc.poll() is not None:
223-
raise RuntimeError('influxdb prematurely exited')
224-
else:
225-
proc.terminate()
226-
proc.wait()
227-
raise RuntimeError('Timeout waiting for influxdb to listen'
228-
' on its ports (%s)' % ports)
229-
except RuntimeError as err:
230-
data = self.get_logs_and_output()
231-
data['reason'] = str(err)
232-
data['now'] = datetime.datetime.now()
233-
raise RuntimeError("%(now)s > %(reason)s. RC=%(rc)s\n"
234-
"stdout=%(out)s\nstderr=%(err)s\nlogs=%(logs)r"
235-
% data)
236-
237-
def get_logs_and_output(self):
238-
proc = self.proc
239-
try:
240-
with open(self.logs_file) as fh:
241-
logs = fh.read()
242-
except IOError as err:
243-
logs = "Couldn't read logs: %s" % err
244-
return {
245-
'rc': proc.returncode,
246-
'out': proc.stdout.read(),
247-
'err': proc.stderr.read(),
248-
'logs': logs
249-
}
250-
251-
def close(self, remove_tree=True):
252-
self.proc.terminate()
253-
self.proc.wait()
254-
if remove_tree:
255-
shutil.rmtree(self.temp_dir_base)
256-
257-
############################################################################
258-
259-
260-
def _setup_influxdb_server(inst):
261-
inst.influxd_inst = InfluxDbInstance(
262-
inst.influxdb_template_conf,
263-
udp_enabled=getattr(inst, 'influxdb_udp_enabled', False))
264-
265-
inst.cli = InfluxDBClient('localhost',
266-
inst.influxd_inst.http_port,
267-
'root',
268-
'',
269-
database='db')
270-
if not using_pypy:
271-
inst.cliDF = DataFrameClient('localhost',
272-
inst.influxd_inst.http_port,
273-
'root',
274-
'',
275-
database='db')
276-
277-
278-
def _unsetup_influxdb_server(inst):
279-
remove_tree = sys.exc_info() == (None, None, None)
280-
inst.influxd_inst.close(remove_tree=remove_tree)
281-
282-
############################################################################
283-
284-
285-
class SingleTestCaseWithServerMixin(object):
286-
''' A mixin for unittest.TestCase to start an influxdb server instance
287-
in a temporary directory **for each test function/case**
288-
'''
289-
290-
# 'influxdb_template_conf' attribute must be set
291-
# on the TestCase class or instance.
292-
293-
setUp = _setup_influxdb_server
294-
tearDown = _unsetup_influxdb_server
295-
296-
297-
class ManyTestCasesWithServerMixin(object):
298-
''' Same than SingleTestCaseWithServerMixin
299-
but creates a single instance for the whole class.
300-
Also pre-creates a fresh database: 'db'.
301-
'''
302-
303-
# 'influxdb_template_conf' attribute must be set on the class itself !
304-
305-
@classmethod
306-
def setUpClass(cls):
307-
_setup_influxdb_server(cls)
308-
309-
def setUp(self):
310-
self.cli.create_database('db')
311-
312-
@classmethod
313-
def tearDownClass(cls):
314-
_unsetup_influxdb_server(cls)
315-
316-
def tearDown(self):
317-
self.cli.drop_database('db')
318-
319-
############################################################################
320-
321-
322-
@unittest.skipIf(not is_influxdb_bin_ok, "could not find influxd binary")
116+
@skipServerTests
323117
class SimpleTests(SingleTestCaseWithServerMixin,
324118
unittest.TestCase):
325119

@@ -492,10 +286,7 @@ def test_revoke_privilege_invalid(self):
492286
ctx.exception.content)
493287

494288

495-
############################################################################
496-
497-
498-
@unittest.skipIf(not is_influxdb_bin_ok, "could not find influxd binary")
289+
@skipServerTests
499290
class CommonTests(ManyTestCasesWithServerMixin,
500291
unittest.TestCase):
501292

@@ -858,9 +649,7 @@ def test_query_multiple_series(self):
858649
self.cli.write_points(pts)
859650

860651

861-
############################################################################
862-
863-
@unittest.skipIf(not is_influxdb_bin_ok, "could not find influxd binary")
652+
@skipServerTests
864653
class UdpTests(ManyTestCasesWithServerMixin,
865654
unittest.TestCase):
866655

0 commit comments

Comments
 (0)