Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 11-19 of 19 total

Windows socket demo program -- uses threads and stuff -- for stress testing the TCP stack

// I wrote this to find out if the claims made at http://laurentszyster.be/blog/tcp-stack-flaking-out/ is
// valid. I disagree with the opinions of the person who posted that TCP flakes out on Windows. I think
// his program has obvious bugs. This program proves that as long as you write your code properly
// the TCP connections do not break randomly. Similar bugs existed in Bittorrent apparently, and they fixed them.
// For more information visit http://sparebandwidth.blogspot.com/2006/08/more-on-tcp-flaking-out.html

#define BUFFER_SIZE 1000
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 9999
#define NUM_THREADS 1000
#define SEND_SOCK_BUFFER_SIZE 34000
#define RECV_SOCK_BUFFER_SIZE  34000
#define SERVER_RECV_SOCK_BUFFER_SIZE  34000
#define SERVER_SEND_SOCK_BUFFER_SIZE 34000
#define CLIENT_LIMIT 1000	/* how many times to send/recv in client */

#include <stdio.h>     
#define FD_SETSIZE  NUM_THREADS
#include <winsock.h>   
#include <stdlib.h>    

#define fatal_error(arg) {\
		fprintf(stderr,"total in %d out %d, %s: %d\n",		\
			total_bytes_received, total_bytes_sent,		\
			arg, WSAGetLastError()); fflush(stderr); exit(1); }
#define fatal_error2(arg)  { fprintf(stderr, "%s", arg); fflush(stderr); exit(1);}

int threads_all_done = 0;

struct thread_args {
	int id;
	int server_sock;
	struct sockaddr_in server_addr;
};

void *client_thread(void *args)
{
	struct thread_args *client_thread_arg;
	struct sockaddr_in server_addr;
	int server_sock;
	int client_sock;
	int on = 1;
	int bytes_received, bytes_sent;
	int num_to_read;
	int total_bytes_received, total_bytes_sent;
	char buffer[BUFFER_SIZE];
	int size;
	int i;

	total_bytes_received = total_bytes_sent = 0;
	
	client_thread_arg = (struct thread_args *)args;
	memcpy(&server_addr, &client_thread_arg->server_addr,
	       sizeof(struct sockaddr_in));
	server_sock = client_thread_arg->server_sock;

	if ((client_sock = socket(PF_INET, SOCK_STREAM,
				  IPPROTO_TCP)) < 0)
		fatal_error("socket() error in client thread");

	if (connect(client_sock, (struct sockaddr *)&server_addr,
		    sizeof(server_addr)) < 0)
		fatal_error("connect() error in client thread");

	/* wait for the server to send startup message */
	if ((bytes_received =
	     recv(client_sock, buffer, BUFFER_SIZE, 0)) < 0)
		fatal_error("recv() error in client thread");

	if (ioctlsocket(client_sock, FIONBIO, &on) < 0)
		fatal_error("FIONBIO error in client thread");

	size = SEND_SOCK_BUFFER_SIZE;
	if (setsockopt(client_sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
		fatal_error("SO_SNDBUF error in client thread");
	size = RECV_SOCK_BUFFER_SIZE;
	if (setsockopt(client_sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
		fatal_error("SO_RCVBUF error in client thread");
	
	for (i = 0; i < CLIENT_LIMIT ; i++) {
		int errno;
		
		if ((bytes_sent =
		     send(client_sock, buffer,
			  BUFFER_SIZE, 0)) != BUFFER_SIZE) {
			errno = WSAGetLastError();
			if (errno == WSAEWOULDBLOCK ||
				errno == WSAENOBUFS)
				continue;
			
			fatal_error("send() error in client thread");
		}
		total_bytes_sent += bytes_sent;

		num_to_read = 0;
		if (ioctlsocket(client_sock, FIONREAD, &num_to_read) < 0) 
			fatal_error("FIONREAD error in client thread");
		
		if (num_to_read == 0)
			continue;
		
		if ((bytes_received =
		     recv(client_sock, buffer, 
			  num_to_read >= BUFFER_SIZE ?
			  BUFFER_SIZE - 1 : num_to_read, 0)) <= 0)
			fatal_error("recv() error in client thread");
		total_bytes_received += bytes_received; 		
	}

	printf("thread %d total bytes received %d sent %d\n",
	       client_thread_arg->id, total_bytes_received, total_bytes_sent);

#if 0
	closesocket(client_sock);
#endif
	free(args);
}

void *starter_thread(void *args)
{
	HANDLE thread_handles[NUM_THREADS];
	DWORD thread_ids[NUM_THREADS];
	struct thread_args *client_thread_arg;
	int i;
	
	for (i = 0; i < NUM_THREADS; i++) {
		if ((client_thread_arg = 
		     (struct thread_args *)
		     malloc(sizeof(struct thread_args))) == 0) 
			fatal_error2("malloc client_thread_arg error");
		
		memcpy(client_thread_arg, args, sizeof(struct thread_args));
		client_thread_arg->id = i;

		if ((thread_handles[i] =
		     CreateThread(0, 0,
				  (LPTHREAD_START_ROUTINE) client_thread,
				  client_thread_arg, 0,
				  (LPDWORD)&thread_ids[i])) == 0) 
			fatal_error2("CreateThread for clients error");

		printf("created client thread %d\n", i); fflush(stdout);
	}
	free(args);
	args = 0;

	printf("%d threads created\n", NUM_THREADS); fflush(stdout);
	
	for (i = 0; i < NUM_THREADS; i++) 
		WaitForSingleObject(thread_handles[i], INFINITE);
	
	printf("all threads terminated\n"); fflush(stdout);

	threads_all_done = 1;
	
	ExitThread(0);
}

int main(void)
{
	int server_sock, client_sock;    
	struct sockaddr_in server_addr, client_addr; 
	int client_addr_len;
	unsigned short server_port;   
	char buffer[BUFFER_SIZE];    
	int bytes_received, total_bytes_received; 
	int bytes_sent, total_bytes_sent;
	int on = 1;
	unsigned long num_to_read;
	struct timeval timeout;
	struct thread_args *starter_thread_arg;
	WSADATA wsa_data;     
	HANDLE starter_thread_handle;
	DWORD starter_thread_id;
	int client_sockets[NUM_THREADS];
	fd_set socket_fds;
	int size;
	int i;

	total_bytes_received = total_bytes_sent = 0;
	
	if (WSAStartup(MAKEWORD(2, 0), &wsa_data) != 0) {
		fprintf(stderr, "WSAStartup() error");
		exit(1);
	}
	
	total_bytes_received = 0;
	total_bytes_sent = 0;
	
	if ((server_sock = socket(PF_INET, SOCK_STREAM,
				  IPPROTO_TCP)) < 0)
		fatal_error("socket() error");
	
	memset(&client_addr, 0, sizeof(client_addr));     
	memset(&server_addr, 0, sizeof(server_addr));     
	server_addr.sin_family  = AF_INET;       
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
	server_addr.sin_port = htons(SERVER_PORT);
	
	if (bind(server_sock, (struct sockaddr *) &server_addr,
		 sizeof(server_addr)) < 0)
		fatal_error ("bind() error ");
	if (listen(server_sock, 5) < 0)
		fatal_error("listen() error");
	
	if ((starter_thread_arg =
	     (struct thread_args *)
	     malloc(sizeof(struct thread_args))) == 0)
		fatal_error("malloc starter_thread_arg error");

	starter_thread_arg->server_sock = server_sock;
	server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
	memcpy(&starter_thread_arg->server_addr , &server_addr,
	       sizeof(server_addr));
	starter_thread_arg->id = -1;
	
	if ((starter_thread_handle =
	     CreateThread(0,0,
			  (LPTHREAD_START_ROUTINE)starter_thread,
			  starter_thread_arg, 0,
			  (LPDWORD)&starter_thread_id)) == 0)
		fatal_error("CreateThread for starter thread error");
	
	for (i = 0; i < NUM_THREADS; i++) {
		client_addr_len = sizeof(client_addr);
		if ((client_sock = accept(server_sock,
					  (struct sockaddr *) &client_addr,
					  &client_addr_len)) < 0)
			fatal_error("accept() error");
#if 0
		printf("connection accepted from %s\n",
		       inet_ntoa(client_addr.sin_addr));
#endif
		client_sockets[i] = client_sock;
	}
	printf("%d clients accepted\n", NUM_THREADS);

	/* send startup message to all clients */
	for (i = 0; i < NUM_THREADS; i++) {
		int startup_msg_len ;

		client_sock = client_sockets[i];
		memset(buffer, 0, sizeof(buffer));
		strcpy(buffer, "startup");
		startup_msg_len = strlen(buffer);
		if ((bytes_sent =
		     send(client_sock, buffer,
			  startup_msg_len, 0)) != startup_msg_len)
			fatal_error("sending start signal failed");

		size = SERVER_SEND_SOCK_BUFFER_SIZE;
		if (setsockopt(client_sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
			fatal_error("SO_SNDBUF error  ");
		size = SERVER_RECV_SOCK_BUFFER_SIZE;
		if (setsockopt(client_sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
			fatal_error("SO_RCVBUF error ");
	
		if (ioctlsocket(client_sock, FIONBIO, &on) < 0)
			fatal_error("FIONBIO error");
	}

	printf("sent startup messages\n"); fflush(stdout);
	for (;;)  {
		int half = BUFFER_SIZE / 2;

		if (threads_all_done) break;

		Sleep(100);	/* slow down server artificially */
		
		FD_ZERO(&socket_fds);
		for (i = 0; i < NUM_THREADS; i++)
			FD_SET(client_sockets[i], &socket_fds);
		timeout.tv_sec = 0;
		timeout.tv_usec = 10000;

		if (select(0, &socket_fds, 0, 0, &timeout) == 0)
			continue;

		for (i = 0; i < NUM_THREADS; i++) {
			int errno;
			
			if (! FD_ISSET(client_sockets[i], &socket_fds))
				continue;

			client_sock = client_sockets[i];

			/* send half as much */
			if ((bytes_sent =
			     send(client_sock, buffer,
				 half, 0)) != half) {
				errno = WSAGetLastError();
				if (errno == WSAEWOULDBLOCK ||
				    errno == WSAENOBUFS)
					continue;
				fatal_error("send() error");
			}
			total_bytes_sent += bytes_sent;
			
			num_to_read = 0;
			if (ioctlsocket(client_sock, FIONREAD, &num_to_read) < 0) 
				fatal_error("FIONREAD error");
			
			if (num_to_read == 0)
				continue;
			
			/* read half as much */
			num_to_read = num_to_read >= half ? half - 1 : num_to_read;
			if ((bytes_received =
			     recv(client_sock, buffer, num_to_read, 0)) <= 0)
				fatal_error("recv() error ");
			total_bytes_received += bytes_received;
		}
	}
	
	closesocket(server_sock);
	closesocket(client_sock);
	WSACleanup();
	WaitForSingleObject(starter_thread_handle, INFINITE);

	printf("all threads finished. total bytes received %d sent %d\n",
	       total_bytes_received, total_bytes_sent);
	
	exit(0);
}

Generate Rails fixture skeleton using ActiveRecord

In Rails 1.1.5, the basic generator generates the following code for the fixture used in database unit tests:
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first:
  id: 1
another:
  id: 2


As ActiveRecord provides database reflexion features, we can generate a fixture file with all the columns' name prepopulated for number and text types, such as:
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first:
  id: 1
  short_title: short_title_first
  title: title_first


This will be done by the following class:
require_gem 'activerecord'

class RailsFixturesGenerator

  def generate(class_name)
    
    # Get the "Class" object from the class name        
    model_class = Object.const_get(class_name)
    
    yaml_content =  "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n"
    yaml_content += "first:\n"
    
    # get if first!   
    model_class.columns.each { |column|
      
      yaml_content += "  " + column.name + ": "
      
      if column.number?
        yaml_content +=  "1"
      end
      if column.text?
        # @todo /!\ max length
        yaml_content +=  column.name + "_first"
      end
      
      yaml_content += "\n"      
    }  
    
    write_fixture_file(model_class, yaml_content)
    
    yaml_content            
  end  
  
  # Write the <fixture> yaml file  in the test/fixtures folder
  def write_fixture_file(model_class, yaml_content)
    
    path = ENV['DEST'] || "#{RAILS_ROOT}/test/fixtures"
    db   = ENV['DB']   || 'test'
    
    File.open("#{path}/#{model_class.table_name}.yml", 'wb') do |file|    
      file.write yaml_content 
      file.close    
    end
  end
end


Of course, I have an unit test that I wrote before the code ;-)
This was my first "complex" method I wrote in Ruby so please bear with me. Any feedback is welcome. I want to write a Rails plugin in order to share the generators I will write.

Rake task to run a single rails unit or functional test

// stolen from here: http://nubyonrails.com/articles/2006/07/28/foscon-and-living-dangerously-with-rake

##
# Run a single test in Rails.
#
#   rake blogs_list
#   => Runs test_list for BlogsController (functional test)
#
#   rake blog_create
#   => Runs test_create for BlogTest (unit test)

rule "" do |t|
  if /(.*)_([^.]+)$/.match(t.name)
    file_name = $1
    test_name = $2
    if File.exist?("test/unit/#{file_name}_test.rb")
      file_name = "unit/#{file_name}_test.rb" 
    elsif File.exist?("test/functional/#{file_name}_controller_test.rb")
      file_name = "functional/#{file_name}_controller_test.rb" 
    else
      raise "No file found for #{file_name}" 
    end
    sh "ruby -Ilib:test test/#{file_name} -n /^test_#{test_name}/" 
  end
end

Assertions for ActiveRecord validations

These two methods will allow you to assert that an ActiveRecord model should or should not have an validation error.

Put them at the bottom of test/test_helper.rb

  def assert_error_on(field, model)
  	assert !model.errors[field.to_sym].nil?, "No validation error on the #{field.to_s} field."
  end
  
  def assert_no_error_on(field, model)
  	assert model.errors[field.to_sym].nil?, "Validation error on #{field.to_s}."
  end

Time warp for functional and unit testing


Add this at the top of test/test_helper.rb (or elsewhere if not using rails):

# Extend the Time class so that we can offset the time that 'now'
# returns.  This should allow us to effectively time warp for functional
# tests that require limits per hour, what not.
class Time #:nodoc:
  class <<self
    attr_accessor :testing_offset
    alias_method :real_now, :now
    def now
      real_now - testing_offset
    end
    alias_method :new, :now
  end
end
Time.testing_offset = 0


Add this method to Test::Unit::TestCase (in the class definition in test_helper.rb):

  # Time warp to the specified time for the duration of the passed block
  def pretend_now_is(time)
    begin
      Time.testing_offset = Time.now - time
      yield
    ensure
      Time.testing_offset = 0
    end
  end


And now you can write time-based tests. For example:

  def test_should_not_allow_more_than_3_requests_in_last_hour_from_same_ip
    (1..3).each { |n| successful_request }

    start_count = WorkOrderRequest.count
    post :new, :work_order_request => REQUEST_TEMPLATE
    assert_response :redirect
    assert_redirected_to :controller => 'work_order_request',
                         :action => 'limit_exceeded'
    assert_equal start_count, WorkOrderRequest.count
  end

  def test_should_not_allow_more_than_10_requests_in_last_24_hours_from_same_ip
    10.downto(1) do |n|
      pretend_now_is(n.hours.ago) do
        successful_request
      end
    end

    start_count = WorkOrderRequest.count
    post :new, :work_order_request => REQUEST_TEMPLATE
    assert_response :redirect
    assert_redirected_to :controller => 'work_order_request',
                         :action => 'limit_exceeded'
    assert_equal start_count, WorkOrderRequest.count
  end

Partial Mock Object or mocking an instance of an object.

From: http://www.karmiccoding.com/articles/2006/03/11/under-the-hood-with-ruby-partial-mock-objects-for-unit-testing

"What happens though, if you want to override a class in an instance of an object, and not all of its kind? Typically you would define a mock object, and create an instance of it. But, in Ruby there is an easier and faster way that doesn’t involve writing a different mock class for each different scenario – and it is made possible by the singleton class. This clever bit of ruby hackery lets you override the behaviour of a single instance of a class, creating what I’ve decided to call a partial mock object. To demonstrate, I’ve written a small method called override_method which will override the behaviour of the specified method in the passed object, like so:

# Overrides the method +method_name+ in +obj+ with the passed block
def override_method(obj, method_name, &block)
  # Get the singleton class/eigenclass for 'obj'
  klass = class <<obj; self; end 

  # Undefine the old method (using 'send' since 'undef_method' is protected)
  klass.send(:undef_method, method_name)

  # Create the new method
  klass.send(:define_method, method_name, block)
end

# Just an example class
class Foo 
  def do_stuff
    "I'm okay!" 
  end
end

# Test code
list = []
5.times { list.push(Foo.new) }

# We override the method here!
override_method(list.first, :do_stuff) { "I'm NOT okay!" }

list.each_with_index { |f, i| puts "(#{i}) #{f.do_stuff}" }

Outputs:
(0) I'm NOT okay!
(1) I'm okay!
(2) I'm okay!
(3) I'm okay!
(4) I'm okay!

As you can see, only the first object in the array’s behaviour has been changed – the rest have remained untouched. Because of this, you can embed these partial dynamic mock objects deeply into your code without the need to specially instantiate a mock object deep in your code, or writing a ‘clever mock’ to only trigger the determined behaviour in certain objects.

Where this code comes in really handy is when you need an object to raise a difficult to simulate exception (like a disk full error) on a certain method to test your error handling – simply call override_method and pass in a call to raise and voila! Dynamic partial mock objects on the fly!"

Testing Rails Validations

#
# Useful for testing Rails ActiveRecord validations. For more information see:
# http://wiseheartdesign.com/articles/2006/01/16/testing-rails-validations/
#
module ValidationTestHelper
  def assert_valid(field, message, *values)
    __model_check__
    values.each do |value|
      o = __setup_model__(field, value)
      if o.valid?
        assert_block { true }
      else
        messages = [o.errors[field]].flatten
        assert_block("unexpected invalid field <#{o.class}##{field}>, value: <#{value.inspect}>, errors: <#{o.errors[field].inspect}>.") { false }
      end
    end
  end
  
  def assert_invalid(field, message, *values)
    __model_check__
    values.each do |value|
      o = __setup_model__(field, value)
      if o.valid?
        assert_block("field <#{o.class}##{field}> should be invalid for value <#{value.inspect}> with message <#{message.inspect}>") { false }
      else
        messages = [o.errors[field]].flatten
        assert_block("field <#{o.class}##{field}> with value <#{value.inspect}> expected validation error <#{message.inspect}>, but got errors <#{messages.inspect}>") { messages.include?(message) }
      end
    end
  end
  
  def __model_check__
    raise "@model must be assigned in order to use validation assertions" if @model.nil?
    
    o = @model.dup
    raise "@model must be valid before calling a validation assertion, instead @model contained the following errors #{o.errors.instance_variable_get('@errors').inspect}" unless o.valid?
  end
  
  def __setup_model__(field, value)
    o = @model.dup
    attributes = o.instance_variable_get('@attributes')
    o.instance_variable_set('@attributes', attributes.dup)
    o.send("#{field}=", value)
    o
  end
end

Setup for Performance Testing: Clear cache, buffers (MSSQL)

For Microsoft SQL (MSSQL).
Use this to clear the cache and buffers to ensure comparison are accurate.

dbcc freeproccache
go
dbcc dropcleanbuffers
go

Loading data from fixtures in development mode

By Tim Bates.

desc "Load fixtures data into the development database"
task :load_fixtures_data_to_development do
   require 'active_record/fixtures'
   ActiveRecord::Base.establish_connection(
       ActiveRecord::Base.configurations["development"])
   Fixtures.create_fixtures("test/fixtures",
       ActiveRecord::Base.configurations[:fixtures_load_order])
end
« Newer Snippets
Older Snippets »
Showing 11-19 of 19 total