major bug fix with cache.rb, work on implication tests

This commit is contained in:
albert
2010-02-12 15:17:15 -05:00
parent ba05f727b0
commit bc7bd0b386
15 changed files with 206 additions and 520 deletions

View File

@@ -1,210 +0,0 @@
require "danbooru_image_resizer/danbooru_image_resizer"
require "tmpdir"
class PendingPost < ActiveRecord::Base
attr_accessor :file, :image_width, :image_height, :file_ext, :md5, :file_size
belongs_to :uploader, :class_name => "User"
before_save :convert_cgi_file
def process!
update_attribute(:status, "processing")
if is_downloadable?
download_from_source(temp_file_path)
end
self.file_ext = content_type_to_file_ext(content_type)
calculate_hash(file_path)
calculate_file_size(file_path)
calculate_dimensions(file_path) if has_dimensions?
generate_resizes(file_path)
move_file
post = convert_to_post
if post.save
update_attributes(:status => "finished", :post_id => post.id)
else
update_attribute(:status, "error: " + post.errors.full_messages.join(", "))
end
end
def convert_to_post
returning Post.new do |p|
p.tag_string = tag_string
p.md5 = md5
p.file_ext = file_ext
p.image_width = image_width
p.image_height = image_height
p.uploader_id = uploader_id
p.uploader_ip_addr = uploader_ip_addr
p.updater_id = uploader_id
p.updater_ip_addr = uploader_ip_addr
p.rating = rating
p.source = source
p.file_size = file_size
end
end
def move_file
FileUtils.mv(file_path, md5_file_path)
end
def calculate_file_size(source_path)
self.file_size = File.size(source_path)
end
# Calculates the MD5 based on whatever is in temp_file_path
def calculate_hash(source_path)
self.md5 = Digest::MD5.file(source_path).hexdigest
end
class Error < Exception ; end
module ResizerMethods
def generate_resizes(source_path)
generate_resize_for(Danbooru.config.small_image_width, Danbooru.config.small_image_width, source_path)
generate_resize_for(Danbooru.config.medium_image_width, nil, source_path)
generate_resize_for(Danbooru.config.large_image_width, nil, source_path)
end
def generate_resize_for(width, height, source_path)
return if width.nil?
return unless image_width > width
return unless height.nil? || image_height > height
unless File.exists?(source_path)
raise Error.new("file not found")
end
size = Danbooru.reduce_to({:width => image_width, :height => image_height}, {:width => width, :height => height})
# If we're not reducing the resolution, only reencode if the source image larger than
# 200 kilobytes.
if size[:width] == image_width && size[:height] == image_height && File.size?(source_path) < 200.kilobytes
return
end
Danbooru.resize(file_ext, source_path, resized_file_path_for(width), size, 90)
end
end
module DimensionMethods
# Figures out the dimensions of the image.
def calculate_dimensions(file_path)
image_size = ImageSize.new(File.open(file_path, "rb"))
self.image_width = image_size.get_width
self.image_height = image_size.get_height
end
# Does this file have image dimensions?
def has_dimensions?
%w(jpg gif png swf).include?(file_ext)
end
end
module ContentTypeMethods
def content_type_to_file_ext(content_type)
case content_type
when "image/jpeg"
"jpg"
when "image/gif"
"gif"
when "image/png"
"png"
when "application/x-shockwave-flash"
"swf"
else
"bin"
end
end
# Converts a content type string to a file extension
def file_ext_to_content_type(file_ext)
case file_ext
when /\.jpeg$|\.jpg$/
"image/jpeg"
when /\.gif$/
"image/gif"
when /\.png$/
"image/png"
when /\.swf$/
"application/x-shockwave-flash"
else
"application/octet-stream"
end
end
end
module FilePathMethods
def md5_file_path
prefix = Rails.env == "test" ? "test." : ""
"#{Rails.root}/public/data/original/#{prefix}#{md5}.#{file_ext}"
end
def resized_file_path_for(width)
prefix = Rails.env == "test" ? "test." : ""
case width
when Danbooru.config.small_image_width
"#{Rails.root}/public/data/thumb/#{prefix}#{md5}.jpg"
when Danbooru.config.medium_image_width
"#{Rails.root}/public/data/medium/#{prefix}#{md5}.jpg"
when Danbooru.config.large_image_width
"#{Rails.root}/public/data/large/#{prefix}#{md5}.jpg"
end
end
def temp_file_path
File.join(Dir::tmpdir, "#{Time.now.to_f}.#{$PROCESS_ID}")
end
end
module DownloaderMethods
# Determines whether the source is downloadable
def is_downloadable?
source =~ /^http:\/\// && file_path.blank?
end
# Downloads the file to destination_path
def download_from_source(destination_path)
download = Download.new(source, destination_path)
download.download!
self.file_path = destination_path
self.content_type = download.content_type || file_ext_to_content_type(source)
self.file_ext = content_type_to_file_ext(content_type)
self.source = download.source
end
end
module CgiFileMethods
def convert_cgi_file
return if file.blank? || file.size == 0
if file.local_path
self.file_path = file.local_path
else
self.file_path = temp_file_path
File.open(file_path, 'wb') do |out|
out.write(file.read)
end
end
self.content_type = file.content_type || file_ext_to_content_type(file.original_filename)
self.file_ext = content_type_to_file_ext(content_type)
end
end
include ResizerMethods
include DimensionMethods
include ContentTypeMethods
include DownloaderMethods
include FilePathMethods
include CgiFileMethods
end

View File

@@ -1,9 +1,10 @@
class TagAlias < ActiveRecord::Base class TagAlias < ActiveRecord::Base
attr_accessor :updater_id, :updater_ip_addr attr_accessor :updater_id, :updater_ip_addr
after_save :update_posts after_save :update_posts
after_save :update_cache after_destroy :clear_cache
validates_presence_of :updater_id, :updater_ip_addr validates_presence_of :updater_id, :updater_ip_addr
validates_uniqueness_of :antecedent_name validates_uniqueness_of :antecedent_name
validate :absence_of_transitive_relation
belongs_to :updater, :class_name => "User" belongs_to :updater, :class_name => "User"
belongs_to :creator, :class_name => "User" belongs_to :creator, :class_name => "User"
@@ -20,8 +21,20 @@ class TagAlias < ActiveRecord::Base
alias_hash.values.uniq alias_hash.values.uniq
end end
def absence_of_transitive_relation
# We don't want a -> b && b -> c chains
if self.class.exists?(["antecedent_name = ?", consequent_name]) || self.class.exists?(["consequent_name = ?", antecedent_name])
self.errors[:base] << "Tag alias can not create a transitive relation with another tag alias"
false
end
end
def clear_cache
Cache.delete("ta:#{Cache.sanitize(antecedent_name)}")
end
def update_cache def update_cache
Cache.put("ta:#{Cache.sanitize(antecedent_name)}", consequent_name, 24.hours) Cache.put("ta:#{Cache.sanitize(antecedent_name)}", consequent_name)
end end
def update_posts def update_posts

View File

@@ -1,32 +1,82 @@
class TagImplication < ActiveRecord::Base class TagImplication < ActiveRecord::Base
after_save :update_descendant_names attr_accessor :updater_id, :updater_ip_addr
before_save :update_descendant_names
after_save :update_descendant_names_for_parent
after_save :clear_cache
after_destroy :clear_cache
after_save :update_posts
belongs_to :creator, :class_name => "User"
belongs_to :updater, :class_name => "User"
validates_presence_of :updater_id, :updater_ip_addr, :creator_id
def self.with_descendants(names) def self.with_descendants(names)
names.map do |name| names.map do |name|
ti = TagImplication.find_by_antecedent_name(name) ti = find_by_antecedent_name(name)
if ti if ti
[name, ti.descendant_name_array] [name, ti.descendant_names_array]
else else
name name
end end
end.flatten end.flatten
end end
def parent
@parent ||= self.class.where(["consequent_name = ?", antecedent_name]).first
end
def descendants def descendants
all = [] all = []
children = [consequent_name] children = [consequent_name]
until children.empty? until children.empty?
all += children all += children
children = where(["antecedent_name IN (?)", children]).all.map(&:consequent_name) children = self.class.where(["antecedent_name IN (?)", children]).all.map(&:consequent_name)
end
all
end
def descendant_names_array
Cache.get("ti:#{Cache.sanitize(antecedent_name)}") do
descendant_names.split(/ /)
end end
end end
def descendant_name_array def update_descendant_names
descendant_names.split(/ /)
end
def update_desecendant_names
self.descendant_names = descendants.join(" ") self.descendant_names = descendants.join(" ")
end end
def update_descendant_names!
update_descendant_names
save
end
def update_descendant_names_for_parent
parent.update_descendant_names! if parent
end
def clear_cache
Cache.delete("ti:#{Cache.sanitize(antecedent_name)}")
end
def update_posts
Post.find_by_tags(antecedent_name).find_each do |post|
escaped_antecedent_name = Regexp.escape(antecedent_name)
fixed_tags = post.tag_string.sub(/\A#{escaped_antecedent_name} | #{escaped_antecedent_name} | #{escaped_antecedent_name}\Z/, " #{descendant_names} ").strip
post.update_attributes(
:tag_string => fixed_tags,
:updater_id => updater_id,
:updater_ip_addr => updater_ip_addr
)
end
end
def reload(options = {})
super
clear_parent_cache
end
def clear_parent_cache
@parent = nil
end
end end

View File

@@ -374,45 +374,6 @@ CREATE SEQUENCE favorites_9_id_seq
ALTER SEQUENCE favorites_9_id_seq OWNED BY favorites_9.id; ALTER SEQUENCE favorites_9_id_seq OWNED BY favorites_9.id;
--
-- Name: pending_posts; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE pending_posts (
id integer NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
source character varying(255),
file_path character varying(255),
content_type character varying(255),
rating character(1) NOT NULL,
uploader_id integer NOT NULL,
uploader_ip_addr inet NOT NULL,
tag_string text NOT NULL,
status character varying(255) DEFAULT 'pending'::character varying NOT NULL,
post_id integer
);
--
-- Name: pending_posts_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE pending_posts_id_seq
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- Name: pending_posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE pending_posts_id_seq OWNED BY pending_posts.id;
-- --
-- Name: pool_versions; Type: TABLE; Schema: public; Owner: -; Tablespace: -- Name: pool_versions; Type: TABLE; Schema: public; Owner: -; Tablespace:
-- --
@@ -724,6 +685,45 @@ CREATE SEQUENCE unapprovals_id_seq
ALTER SEQUENCE unapprovals_id_seq OWNED BY unapprovals.id; ALTER SEQUENCE unapprovals_id_seq OWNED BY unapprovals.id;
--
-- Name: uploads; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE uploads (
id integer NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
source character varying(255),
file_path character varying(255),
content_type character varying(255),
rating character(1) NOT NULL,
uploader_id integer NOT NULL,
uploader_ip_addr inet NOT NULL,
tag_string text NOT NULL,
status character varying(255) DEFAULT 'pending'::character varying NOT NULL,
post_id integer
);
--
-- Name: uploads_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE uploads_id_seq
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE
CACHE 1;
--
-- Name: uploads_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE uploads_id_seq OWNED BY uploads.id;
-- --
-- Name: users; Type: TABLE; Schema: public; Owner: -; Tablespace: -- Name: users; Type: TABLE; Schema: public; Owner: -; Tablespace:
-- --
@@ -843,13 +843,6 @@ ALTER TABLE favorites_8 ALTER COLUMN id SET DEFAULT nextval('favorites_8_id_seq'
ALTER TABLE favorites_9 ALTER COLUMN id SET DEFAULT nextval('favorites_9_id_seq'::regclass); ALTER TABLE favorites_9 ALTER COLUMN id SET DEFAULT nextval('favorites_9_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE pending_posts ALTER COLUMN id SET DEFAULT nextval('pending_posts_id_seq'::regclass);
-- --
-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- Name: id; Type: DEFAULT; Schema: public; Owner: -
-- --
@@ -906,6 +899,13 @@ ALTER TABLE tags ALTER COLUMN id SET DEFAULT nextval('tags_id_seq'::regclass);
ALTER TABLE unapprovals ALTER COLUMN id SET DEFAULT nextval('unapprovals_id_seq'::regclass); ALTER TABLE unapprovals ALTER COLUMN id SET DEFAULT nextval('unapprovals_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE uploads ALTER COLUMN id SET DEFAULT nextval('uploads_id_seq'::regclass);
-- --
-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- Name: id; Type: DEFAULT; Schema: public; Owner: -
-- --
@@ -993,14 +993,6 @@ ALTER TABLE ONLY favorites_9
ADD CONSTRAINT favorites_9_pkey PRIMARY KEY (id); ADD CONSTRAINT favorites_9_pkey PRIMARY KEY (id);
--
-- Name: pending_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY pending_posts
ADD CONSTRAINT pending_posts_pkey PRIMARY KEY (id);
-- --
-- Name: pool_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- Name: pool_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
-- --
@@ -1065,6 +1057,14 @@ ALTER TABLE ONLY unapprovals
ADD CONSTRAINT unapprovals_pkey PRIMARY KEY (id); ADD CONSTRAINT unapprovals_pkey PRIMARY KEY (id);
--
-- Name: uploads_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY uploads
ADD CONSTRAINT uploads_pkey PRIMARY KEY (id);
-- --
-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
-- --

View File

@@ -1,21 +0,0 @@
class CreatePendingPosts < ActiveRecord::Migration
def self.up
create_table :pending_posts do |t|
t.timestamps
t.column :source, :string
t.column :file_path, :string
t.column :content_type, :string
t.column :rating, :character, :null => false
t.column :uploader_id, :integer, :null => false
t.column :uploader_ip_addr, "inet", :null => false
t.column :tag_string, :text, :null => false
t.column :status, :string, :null => false, :default => "pending"
t.column :post_id, :integer
end
end
def self.down
drop_table :pending_posts
end
end

View File

@@ -9,6 +9,7 @@ class CreateTagAliases < ActiveRecord::Migration
end end
add_index :tag_aliases, :antecedent_name add_index :tag_aliases, :antecedent_name
add_index :tag_aliases, :consequent_name
end end
def self.down def self.down

View File

@@ -10,6 +10,7 @@ class CreateTagImplications < ActiveRecord::Migration
end end
add_index :tag_implications, :antecedent_name add_index :tag_implications, :antecedent_name
add_index :tag_implications, :consequent_name
end end
def self.down def self.down

View File

@@ -25,7 +25,9 @@ module Cache
hash[x] = "#{prefix}:#{Cache.sanitize(x)}" hash[x] = "#{prefix}:#{Cache.sanitize(x)}"
hash hash
end end
start_time = Time.now
sanitized_key_to_value_hash = MEMCACHE.get_multi(key_to_sanitized_key_hash.values) sanitized_key_to_value_hash = MEMCACHE.get_multi(key_to_sanitized_key_hash.values)
elapsed = Time.now - start_time
returning({}) do |result_hash| returning({}) do |result_hash|
key_to_sanitized_key_hash.each do |key, sanitized_key| key_to_sanitized_key_hash.each do |key, sanitized_key|
if sanitized_key_to_value_hash.has_key?(sanitized_key) if sanitized_key_to_value_hash.has_key?(sanitized_key)
@@ -35,16 +37,12 @@ module Cache
Cache.put(sanitized_key, result_hash[key], expiry) Cache.put(sanitized_key, result_hash[key], expiry)
end end
end end
ActiveRecord::Base.logger.debug('MemCache Multi-Get (%0.6f) %s' % [elapsed, keys.join(",")])
end end
end end
def get(key, expiry = 0) def get(key, expiry = 0)
if block_given?
return yield
else
return nil
end
begin begin
start_time = Time.now start_time = Time.now
value = MEMCACHE.get key value = MEMCACHE.get key

View File

@@ -1,43 +0,0 @@
require 'fileutils'
Factory.define(:pending_post) do |f|
f.rating "s"
f.uploader {|x| x.association(:user)}
f.uploader_ip_addr "127.0.0.1"
f.tag_string "special"
f.status "pending"
end
Factory.define(:downloadable_pending_post, :parent => :pending_post) do |f|
f.source "http://www.google.com/intl/en_ALL/images/logo.gif"
end
Factory.define(:uploaded_jpg_pending_post, :parent => :pending_post) do |f|
f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.jpg"
end
end
Factory.define(:uploaded_large_jpg_pending_post, :parent => :pending_post) do |f|
f.file_ext "jpg"
f.content_type "image/jpeg"
f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test-large.jpg", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test-large.jpg"
end
end
Factory.define(:uploaded_png_pending_post, :parent => :pending_post) do |f|
f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.png", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.png"
end
end
Factory.define(:uploaded_gif_pending_post, :parent => :pending_post) do |f|
f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.gif", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.gif"
end
end

View File

@@ -0,0 +1,5 @@
Factory.define(:tag_implication) do |f|
f.creator {|x| x.association(:user)}
f.updater_id {|x| x.creator_id}
f.updater_ip_addr "127.0.0.1"
end

View File

@@ -8,18 +8,18 @@ Factory.define(:upload) do |f|
f.status "pending" f.status "pending"
end end
Factory.define(:downloadable_upload, :parent => :upload) do |f| Factory.define(:source_upload, :parent => :upload) do |f|
f.source "http://www.google.com/intl/en_ALL/images/logo.gif" f.source "http://www.google.com/intl/en_ALL/images/logo.gif"
end end
Factory.define(:uploaded_jpg_upload, :parent => :upload) do |f| Factory.define(:jpg_upload, :parent => :upload) do |f|
f.file_path do f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp") FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.jpg" "#{Rails.root}/tmp/test.jpg"
end end
end end
Factory.define(:uploaded_large_jpg_upload, :parent => :upload) do |f| Factory.define(:large_jpg_upload, :parent => :upload) do |f|
f.file_ext "jpg" f.file_ext "jpg"
f.content_type "image/jpeg" f.content_type "image/jpeg"
f.file_path do f.file_path do
@@ -28,14 +28,14 @@ Factory.define(:uploaded_large_jpg_upload, :parent => :upload) do |f|
end end
end end
Factory.define(:uploaded_png_upload, :parent => :upload) do |f| Factory.define(:png_upload, :parent => :upload) do |f|
f.file_path do f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.png", "#{Rails.root}/tmp") FileUtils.cp("#{Rails.root}/test/files/test.png", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.png" "#{Rails.root}/tmp/test.png"
end end
end end
Factory.define(:uploaded_gif_upload, :parent => :upload) do |f| Factory.define(:gif_upload, :parent => :upload) do |f|
f.file_path do f.file_path do
FileUtils.cp("#{Rails.root}/test/files/test.gif", "#{Rails.root}/tmp") FileUtils.cp("#{Rails.root}/test/files/test.gif", "#{Rails.root}/tmp")
"#{Rails.root}/tmp/test.gif" "#{Rails.root}/tmp/test.gif"

View File

@@ -1,156 +0,0 @@
require File.dirname(__FILE__) + '/../test_helper'
class PendingPostTest < ActiveSupport::TestCase
context "A pending post" do
teardown do
FileUtils.rm_f(Dir.glob("#{Rails.root}/tmp/test.*"))
end
context "image size calculator" do
should "discover the dimensions for a JPG" do
@pending_post = Factory.create(:uploaded_jpg_pending_post)
assert_nothing_raised {@pending_post.calculate_dimensions(@pending_post.file_path)}
assert_equal(500, @pending_post.image_width)
assert_equal(335, @pending_post.image_height)
end
should "discover the dimensions for a PNG" do
@pending_post = Factory.create(:uploaded_png_pending_post)
assert_nothing_raised {@pending_post.calculate_dimensions(@pending_post.file_path)}
assert_equal(768, @pending_post.image_width)
assert_equal(1024, @pending_post.image_height)
end
should "discover the dimensions for a GIF" do
@pending_post = Factory.create(:uploaded_gif_pending_post)
assert_nothing_raised {@pending_post.calculate_dimensions(@pending_post.file_path)}
assert_equal(400, @pending_post.image_width)
assert_equal(400, @pending_post.image_height)
end
end
context "content type calculator" do
should "know how to parse jpeg, png, gif, and swf file extensions" do
@pending_post = Factory.create(:uploaded_jpg_pending_post)
assert_equal("image/jpeg", @pending_post.file_ext_to_content_type("test.jpeg"))
assert_equal("image/gif", @pending_post.file_ext_to_content_type("test.gif"))
assert_equal("image/png", @pending_post.file_ext_to_content_type("test.png"))
assert_equal("application/x-shockwave-flash", @pending_post.file_ext_to_content_type("test.swf"))
assert_equal("application/octet-stream", @pending_post.file_ext_to_content_type(""))
end
should "know how to parse jpeg, png, gif, and swf content types" do
@pending_post = Factory.create(:uploaded_jpg_pending_post)
assert_equal("jpg", @pending_post.content_type_to_file_ext("image/jpeg"))
assert_equal("gif", @pending_post.content_type_to_file_ext("image/gif"))
assert_equal("png", @pending_post.content_type_to_file_ext("image/png"))
assert_equal("swf", @pending_post.content_type_to_file_ext("application/x-shockwave-flash"))
assert_equal("bin", @pending_post.content_type_to_file_ext(""))
end
end
context "downloader" do
should "initialize the final path and content type after downloading a file" do
@pending_post = Factory.create(:downloadable_pending_post)
path = "#{Rails.root}/tmp/test.download.jpg"
assert_nothing_raised {@pending_post.download_from_source(path)}
assert(File.exists?(path))
assert_equal(8558, File.size(path))
assert_equal("image/gif", @pending_post.content_type)
assert_equal(path, @pending_post.file_path)
assert_equal("gif", @pending_post.file_ext)
end
end
context "file processor" do
should "parse and process a cgi file representation" do
FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp")
@pending_post = PendingPost.new(:file => upload_jpeg("#{Rails.root}/tmp/test.jpg"))
assert_nothing_raised {@pending_post.convert_cgi_file}
assert_equal("image/jpeg", @pending_post.content_type)
assert(File.exists?(@pending_post.file_path))
assert_equal(28086, File.size(@pending_post.file_path))
assert_equal("jpg", @pending_post.file_ext)
end
end
context "hash calculator" do
should "caculate the hash" do
@pending_post = Factory.create(:uploaded_jpg_pending_post)
@pending_post.calculate_hash(@pending_post.file_path)
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @pending_post.md5)
end
end
context "resizer" do
teardown do
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/thumb/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/medium/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/large/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/original/test.*.jpg"))
end
should "generate several resized versions of the image" do
@pending_post = Factory.create(:uploaded_large_jpg_pending_post)
@pending_post.calculate_hash(@pending_post.file_path)
@pending_post.calculate_dimensions(@pending_post.file_path)
assert_nothing_raised {@pending_post.generate_resizes(@pending_post.file_path)}
assert(File.exists?(@pending_post.resized_file_path_for(Danbooru.config.small_image_width)))
assert_equal(6556, File.size(@pending_post.resized_file_path_for(Danbooru.config.small_image_width)))
assert(File.exists?(@pending_post.resized_file_path_for(Danbooru.config.medium_image_width)))
assert_equal(39411, File.size(@pending_post.resized_file_path_for(Danbooru.config.medium_image_width)))
assert(File.exists?(@pending_post.resized_file_path_for(Danbooru.config.large_image_width)))
assert_equal(179324, File.size(@pending_post.resized_file_path_for(Danbooru.config.large_image_width)))
end
end
should "process completely for a downloaded image" do
@pending_post = Factory.create(:downloadable_pending_post,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
assert_difference("Post.count") do
assert_nothing_raised {@pending_post.process!}
end
post = Post.last
assert_equal("hoge foo", post.tag_string)
assert_equal("s", post.rating)
assert_equal(@pending_post.uploader_id, post.uploader_id)
assert_equal("127.0.0.1", post.uploader_ip_addr)
assert_equal(@pending_post.md5, post.md5)
assert_equal("gif", post.file_ext)
assert_equal(276, post.image_width)
assert_equal(110, post.image_height)
assert_equal(8558, post.file_size)
assert_equal(post.id, @pending_post.post_id)
assert_equal("finished", @pending_post.status)
end
end
should "process completely for an uploaded image" do
@pending_post = Factory.create(:uploaded_jpg_pending_post,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
@pending_post.file = upload_jpeg("#{Rails.root}/test/files/test.jpg")
@pending_post.convert_cgi_file
assert_difference("Post.count") do
assert_nothing_raised {@pending_post.process!}
end
post = Post.last
assert_equal("hoge foo", post.tag_string)
assert_equal("s", post.rating)
assert_equal(@pending_post.uploader_id, post.uploader_id)
assert_equal("127.0.0.1", post.uploader_ip_addr)
assert_equal(@pending_post.md5, post.md5)
assert_equal("jpg", post.file_ext)
assert(File.exists?(post.file_path))
assert_equal(28086, File.size(post.file_path))
assert_equal(post.id, @pending_post.post_id)
assert_equal("finished", @pending_post.status)
end
end

View File

@@ -19,6 +19,8 @@ class TagAliasTest < ActiveSupport::TestCase
tag2 = Factory.create(:tag, :name => "bbb") tag2 = Factory.create(:tag, :name => "bbb")
ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb") ta = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
assert_equal("bbb", MEMCACHE.get("ta:aaa")) assert_equal("bbb", MEMCACHE.get("ta:aaa"))
ta.destroy
assert_nil(MEMCACHE.get("ta:aaa"))
end end
should "update any affected posts when saved" do should "update any affected posts when saved" do
@@ -33,5 +35,14 @@ class TagAliasTest < ActiveSupport::TestCase
assert_equal("ccc bbb", post1.tag_string) assert_equal("ccc bbb", post1.tag_string)
assert_equal("ccc ddd", post2.tag_string) assert_equal("ccc ddd", post2.tag_string)
end end
should "not validate for transitive relations" do
ta1 = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
assert_difference("TagAlias.count", 0) do
ta3 = TagAlias.create(:antecedent_name => "bbb", :consequent_name => "ddd", :updater_id => ta1.creator_id, :updater_ip_addr => "127.0.0.1")
assert(ta3.errors.any?, "Tag alias should be invalid")
assert_equal("Tag alias can not create a transitive relation with another tag alias", ta3.errors.full_messages.join)
end
end
end end
end end

View File

@@ -1,8 +1,45 @@
require 'test_helper' require File.dirname(__FILE__) + '/../test_helper'
class TagImplicationTest < ActiveSupport::TestCase class TagImplicationTest < ActiveSupport::TestCase
# Replace this with your real tests. context "A tag implication" do
test "the truth" do setup do
assert true MEMCACHE.flush_all
@user = Factory.create(:user)
end
should "clear the cache upon saving" do
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
assert_equal(["bbb"], ti1.descendant_names_array)
assert_equal(["bbb"], MEMCACHE.get("ti:aaa"))
ti1.update_attributes(
:consequent_name => "ccc",
:updater_id => @user.id,
:updater_ip_addr => "127.0.0.1"
)
assert_nil(MEMCACHE.get("ti:aaa"))
end
# should "clear the cache upon destruction" do
# ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
# assert_equal("bbb", ti1.descendant_names)
# assert_equal(["bbb"], ti1.descendant_names_array)
# assert_equal(["bbb"], MEMCACHE.get("ti:aaa"))
# ti1.destroy
# assert_nil(MEMCACHE.get("ti:aaa"))
# end
#
# should "calculate all its descendants" do
# ti1 = Factory.create(:tag_implication, :antecedent_name => "bbb", :consequent_name => "ccc")
# assert_equal(["ccc"], ti1.descendant_names_array)
# ti2 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "bbb")
# assert_equal(["bbb", "ccc"], ti2.descendant_names_array)
# ti1.reload
# assert_equal(["ccc"], ti1.descendant_names_array)
# end
should "cache its descendants"
should "update its descendants on save"
should "update the decendants for its parent on save"
should "update any affected post upon save"
end end
end end

View File

@@ -8,21 +8,21 @@ class UploadTest < ActiveSupport::TestCase
context "image size calculator" do context "image size calculator" do
should "discover the dimensions for a JPG" do should "discover the dimensions for a JPG" do
@upload = Factory.create(:uploaded_jpg_upload) @upload = Factory.create(:jpg_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)} assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(500, @upload.image_width) assert_equal(500, @upload.image_width)
assert_equal(335, @upload.image_height) assert_equal(335, @upload.image_height)
end end
should "discover the dimensions for a PNG" do should "discover the dimensions for a PNG" do
@upload = Factory.create(:uploaded_png_upload) @upload = Factory.create(:png_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)} assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(768, @upload.image_width) assert_equal(768, @upload.image_width)
assert_equal(1024, @upload.image_height) assert_equal(1024, @upload.image_height)
end end
should "discover the dimensions for a GIF" do should "discover the dimensions for a GIF" do
@upload = Factory.create(:uploaded_gif_upload) @upload = Factory.create(:gif_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)} assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(400, @upload.image_width) assert_equal(400, @upload.image_width)
assert_equal(400, @upload.image_height) assert_equal(400, @upload.image_height)
@@ -31,7 +31,7 @@ class UploadTest < ActiveSupport::TestCase
context "content type calculator" do context "content type calculator" do
should "know how to parse jpeg, png, gif, and swf file extensions" do should "know how to parse jpeg, png, gif, and swf file extensions" do
@upload = Factory.create(:uploaded_jpg_upload) @upload = Factory.create(:jpg_upload)
assert_equal("image/jpeg", @upload.file_ext_to_content_type("test.jpeg")) assert_equal("image/jpeg", @upload.file_ext_to_content_type("test.jpeg"))
assert_equal("image/gif", @upload.file_ext_to_content_type("test.gif")) assert_equal("image/gif", @upload.file_ext_to_content_type("test.gif"))
assert_equal("image/png", @upload.file_ext_to_content_type("test.png")) assert_equal("image/png", @upload.file_ext_to_content_type("test.png"))
@@ -40,7 +40,7 @@ class UploadTest < ActiveSupport::TestCase
end end
should "know how to parse jpeg, png, gif, and swf content types" do should "know how to parse jpeg, png, gif, and swf content types" do
@upload = Factory.create(:uploaded_jpg_upload) @upload = Factory.create(:jpg_upload)
assert_equal("jpg", @upload.content_type_to_file_ext("image/jpeg")) assert_equal("jpg", @upload.content_type_to_file_ext("image/jpeg"))
assert_equal("gif", @upload.content_type_to_file_ext("image/gif")) assert_equal("gif", @upload.content_type_to_file_ext("image/gif"))
assert_equal("png", @upload.content_type_to_file_ext("image/png")) assert_equal("png", @upload.content_type_to_file_ext("image/png"))
@@ -51,7 +51,7 @@ class UploadTest < ActiveSupport::TestCase
context "downloader" do context "downloader" do
should "initialize the final path and content type after downloading a file" do should "initialize the final path and content type after downloading a file" do
@upload = Factory.create(:downloadable_upload) @upload = Factory.create(:source_upload)
path = "#{Rails.root}/tmp/test.download.jpg" path = "#{Rails.root}/tmp/test.download.jpg"
assert_nothing_raised {@upload.download_from_source(path)} assert_nothing_raised {@upload.download_from_source(path)}
assert(File.exists?(path)) assert(File.exists?(path))
@@ -76,7 +76,7 @@ class UploadTest < ActiveSupport::TestCase
context "hash calculator" do context "hash calculator" do
should "caculate the hash" do should "caculate the hash" do
@upload = Factory.create(:uploaded_jpg_upload) @upload = Factory.create(:jpg_upload)
@upload.calculate_hash(@upload.file_path) @upload.calculate_hash(@upload.file_path)
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5) assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5)
end end
@@ -91,7 +91,7 @@ class UploadTest < ActiveSupport::TestCase
end end
should "generate several resized versions of the image" do should "generate several resized versions of the image" do
@upload = Factory.create(:uploaded_large_jpg_upload) @upload = Factory.create(:large_jpg_upload)
@upload.calculate_hash(@upload.file_path) @upload.calculate_hash(@upload.file_path)
@upload.calculate_dimensions(@upload.file_path) @upload.calculate_dimensions(@upload.file_path)
assert_nothing_raised {@upload.generate_resizes(@upload.file_path)} assert_nothing_raised {@upload.generate_resizes(@upload.file_path)}
@@ -105,7 +105,7 @@ class UploadTest < ActiveSupport::TestCase
end end
should "process completely for a downloaded image" do should "process completely for a downloaded image" do
@upload = Factory.create(:downloadable_upload, @upload = Factory.create(:source_upload,
:rating => "s", :rating => "s",
:uploader_ip_addr => "127.0.0.1", :uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo" :tag_string => "hoge foo"
@@ -130,7 +130,7 @@ class UploadTest < ActiveSupport::TestCase
end end
should "process completely for an uploaded image" do should "process completely for an uploaded image" do
@upload = Factory.create(:uploaded_jpg_upload, @upload = Factory.create(:jpg_upload,
:rating => "s", :rating => "s",
:uploader_ip_addr => "127.0.0.1", :uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo" :tag_string => "hoge foo"